summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/xorg
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/xorg')
-rw-r--r--src/gallium/state_trackers/xorg/Makefile37
-rw-r--r--src/gallium/state_trackers/xorg/SConscript27
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.c324
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.h25
-rw-r--r--src/gallium/state_trackers/xorg/xorg_crtc.c67
-rw-r--r--src/gallium/state_trackers/xorg/xorg_dri2.c167
-rw-r--r--src/gallium/state_trackers/xorg/xorg_driver.c110
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c365
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.h41
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.c259
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.h35
-rw-r--r--src/gallium/state_trackers/xorg/xorg_tracker.h29
12 files changed, 1252 insertions, 234 deletions
diff --git a/src/gallium/state_trackers/xorg/Makefile b/src/gallium/state_trackers/xorg/Makefile
index a00ea3e2a4..27a1990724 100644
--- a/src/gallium/state_trackers/xorg/Makefile
+++ b/src/gallium/state_trackers/xorg/Makefile
@@ -1,29 +1,18 @@
-TARGET = libxorgtracker.a
-CFILES = $(wildcard ./*.c)
-OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES))
-GALLIUMDIR = ../..
-TOP = ../../../..
-
+TOP = ../../../..
include $(TOP)/configs/current
-CFLAGS = -DHAVE_CONFIG_H \
- -g -Wall -Wimplicit-function-declaration -fPIC \
- $(shell pkg-config --cflags pixman-1 xorg-server libdrm xproto) \
- -I$(GALLIUMDIR)/include \
- -I$(GALLIUMDIR)/auxiliary \
- -I$(TOP)/src/mesa/drivers/dri/common \
- -I$(TOP)/src/mesa \
- -I$(TOP)/include \
- -I$(TOP)/src/egl/main
-
-#############################################
-
-.PHONY = all clean
+LIBNAME = xorgtracker
-all: $(TARGET)
+LIBRARY_INCLUDES = \
+ -DHAVE_CONFIG_H \
+ $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -I$(TOP)/src/mesa/main
-$(TARGET): $(OBJECTS)
- ar rcs $(TARGET) $(OBJECTS)
+C_SOURCES = $(wildcard ./*.c)
-clean:
- rm -rf $(OBJECTS) $(TARGET)
+include ../../Makefile.template
diff --git a/src/gallium/state_trackers/xorg/SConscript b/src/gallium/state_trackers/xorg/SConscript
new file mode 100644
index 0000000000..65f55ea378
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/SConscript
@@ -0,0 +1,27 @@
+#######################################################################
+# SConscript for xorg state_tracker
+
+Import('*')
+
+if 'xorg' in env['statetrackers']:
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/mesa',
+ ])
+
+ env.ParseConfig('pkg-config --cflags --libs xorg-server')
+
+ st_xorg = env.ConvenienceLibrary(
+ target = 'st_xorg',
+ source = [ 'xorg_composite.c',
+ 'xorg_crtc.c',
+ 'xorg_dri2.c',
+ 'xorg_driver.c',
+ 'xorg_exa.c',
+ 'xorg_exa_tgsi.c',
+ 'xorg_output.c',
+ ]
+ )
+ Export('st_xorg')
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c
new file mode 100644
index 0000000000..af4ae05fb4
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_composite.c
@@ -0,0 +1,324 @@
+#include "xorg_composite.h"
+
+#include "xorg_exa_tgsi.h"
+
+#include <cso_cache/cso_context.h>
+
+#include <pipe/p_inlines.h>
+
+struct xorg_composite_blend {
+ int op:8;
+
+ unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */
+ unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
+
+ unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */
+ unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
+};
+
+#define BLEND_OP_OVER 3
+static const struct xorg_composite_blend xorg_blends[] = {
+ { PictOpClear,
+ PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA,
+ PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
+
+ { PictOpSrc,
+ PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
+ PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
+
+ { PictOpDst,
+ PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
+ PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },
+
+ { PictOpOver,
+ PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
+
+ { PictOpOverReverse,
+ PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
+};
+
+struct acceleration_info {
+ int op : 16;
+ int with_mask : 1;
+ int component_alpha : 1;
+};
+static const struct acceleration_info accelerated_ops[] = {
+ {PictOpClear, 1, 0},
+ {PictOpSrc, 1, 0},
+ {PictOpDst, 1, 0},
+ {PictOpOver, 1, 0},
+ {PictOpOverReverse, 1, 0},
+ {PictOpIn, 1, 0},
+ {PictOpInReverse, 1, 0},
+ {PictOpOut, 1, 0},
+ {PictOpOutReverse, 1, 0},
+ {PictOpAtop, 1, 0},
+ {PictOpAtopReverse, 1, 0},
+ {PictOpXor, 1, 0},
+ {PictOpAdd, 1, 0},
+ {PictOpSaturate, 1, 0},
+};
+
+static struct xorg_composite_blend
+blend_for_op(int op)
+{
+ const int num_blends =
+ sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
+ int i;
+
+ for (i = 0; i < num_blends; ++i) {
+ if (xorg_blends[i].op == op)
+ return xorg_blends[i];
+ }
+ return xorg_blends[BLEND_OP_OVER];
+}
+
+static void
+draw_texture(struct exa_context *exa)
+{
+#if 0
+ if (buf) {
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+#endif
+}
+
+boolean xorg_composite_accelerated(int op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ unsigned i;
+ unsigned accel_ops_count =
+ sizeof(accelerated_ops)/sizeof(struct acceleration_info);
+
+
+ /*FIXME: currently accel is disabled */
+ return FALSE;
+
+ if (pSrcPicture) {
+ /* component alpha not supported */
+ if (pSrcPicture->componentAlpha)
+ return FALSE;
+ /* fills not supported */
+ if (pSrcPicture->pSourcePict)
+ return FALSE;
+ }
+
+ for (i = 0; i < accel_ops_count; ++i) {
+ if (op == accelerated_ops[i].op) {
+ if (pMaskPicture && !accelerated_ops[i].with_mask)
+ return FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+bind_framebuffer_state(struct exa_context *exa, PicturePtr pDstPicture,
+ struct exa_pixmap_priv *pDst)
+{
+ unsigned i;
+ struct pipe_framebuffer_state state;
+ struct pipe_surface *surface = exa_gpu_surface(exa, pDst);
+ memset(&state, 0, sizeof(struct pipe_framebuffer_state));
+
+ state.width = pDstPicture->pDrawable->width;
+ state.height = pDstPicture->pDrawable->height;
+
+ state.nr_cbufs = 1;
+ state.cbufs[0] = surface;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ state.cbufs[i] = 0;
+
+ /* currently we don't use depth/stencil */
+ state.zsbuf = 0;
+
+ cso_set_framebuffer(exa->cso, &state);
+}
+
+enum AxisOrientation {
+ Y0_BOTTOM,
+ Y0_TOP
+};
+
+static void
+set_viewport(struct exa_context *exa, int width, int height,
+ enum AxisOrientation orientation)
+{
+ struct pipe_viewport_state viewport;
+ float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;
+
+ viewport.scale[0] = width / 2.f;
+ viewport.scale[1] = height / y_scale;
+ viewport.scale[2] = 1.0;
+ viewport.scale[3] = 1.0;
+ viewport.translate[0] = width / 2.f;
+ viewport.translate[1] = height / 2.f;
+ viewport.translate[2] = 0.0;
+ viewport.translate[3] = 0.0;
+
+ cso_set_viewport(exa->cso, &viewport);
+}
+
+static void
+bind_viewport_state(struct exa_context *exa, PicturePtr pDstPicture)
+{
+ const int param_bytes = 8 * sizeof(float);
+ int width = pDstPicture->pDrawable->width;
+ int height = pDstPicture->pDrawable->height;
+ float vs_consts[8] = {
+ 2.f/width, 2.f/height, 1, 1,
+ -1, -1, 0, 0
+ };
+ struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer;
+
+ set_viewport(exa, width, height, Y0_BOTTOM);
+
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+ cbuf->buffer = pipe_buffer_create(exa->ctx->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+
+ if (cbuf->buffer) {
+ pipe_buffer_write(exa->ctx->screen, cbuf->buffer,
+ 0, param_bytes, vs_consts);
+ }
+ exa->ctx->set_constant_buffer(exa->ctx, PIPE_SHADER_VERTEX, 0, cbuf);
+}
+
+static void
+bind_blend_state(struct exa_context *exa, int op,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+{
+ boolean component_alpha = pSrcPicture->componentAlpha;
+ struct xorg_composite_blend blend_opt;
+ struct pipe_blend_state blend;
+
+ if (component_alpha) {
+ op = PictOpOver;
+ }
+ blend_opt = blend_for_op(op);
+
+ memset(&blend, 0, sizeof(struct pipe_blend_state));
+ blend.blend_enable = 1;
+ blend.colormask |= PIPE_MASK_R;
+ blend.colormask |= PIPE_MASK_G;
+ blend.colormask |= PIPE_MASK_B;
+ blend.colormask |= PIPE_MASK_A;
+
+ blend.rgb_src_factor = blend_opt.rgb_src_factor;
+ blend.alpha_src_factor = blend_opt.alpha_src_factor;
+ blend.rgb_dst_factor = blend_opt.rgb_dst_factor;
+ blend.alpha_dst_factor = blend_opt.alpha_dst_factor;
+
+ cso_set_blend(exa->cso, &blend);
+}
+
+static void
+bind_rasterizer_state(struct exa_context *exa)
+{
+ struct pipe_rasterizer_state raster;
+ memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
+ raster.gl_rasterization_rules = 1;
+ cso_set_rasterizer(exa->cso, &raster);
+}
+
+static void
+bind_shaders(struct exa_context *exa, int op,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+{
+ unsigned vs_traits = 0, fs_traits = 0;
+ struct xorg_shader shader;
+
+ if (pSrcPicture) {
+ vs_traits |= VS_COMPOSITE;
+ fs_traits |= FS_COMPOSITE;
+ }
+
+ if (pMaskPicture) {
+ vs_traits |= VS_MASK;
+ fs_traits |= FS_MASK;
+ }
+
+ shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(exa->cso, shader.vs);
+ cso_set_fragment_shader_handle(exa->cso, shader.fs);
+}
+
+
+static void
+bind_samplers(struct exa_context *exa, int op,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture,
+ struct exa_pixmap_priv *pSrc,
+ struct exa_pixmap_priv *pMask,
+ struct exa_pixmap_priv *pDst)
+{
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state src_sampler, mask_sampler;
+
+ memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
+ memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
+
+ if (pSrcPicture && pSrc) {
+ src_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ src_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ src_sampler.normalized_coords = 1;
+ samplers[0] = &src_sampler;
+ textures[0] = pSrc->tex;
+ }
+
+ if (pMaskPicture && pMask) {
+ mask_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ mask_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ mask_sampler.normalized_coords = 1;
+ samplers[1] = &mask_sampler;
+ textures[1] = pMask->tex;
+ }
+
+ cso_set_samplers(exa->cso, 3,
+ (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_textures(exa->cso, 3, textures);
+}
+
+boolean xorg_composite_bind_state(struct exa_context *exa,
+ int op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture,
+ struct exa_pixmap_priv *pSrc,
+ struct exa_pixmap_priv *pMask,
+ struct exa_pixmap_priv *pDst)
+{
+ bind_framebuffer_state(exa, pDstPicture, pDst);
+ bind_viewport_state(exa, pDstPicture);
+ bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
+ bind_rasterizer_state(exa);
+ bind_shaders(exa, op, pSrcPicture, pMaskPicture);
+ bind_samplers(exa, op, pSrcPicture, pMaskPicture, pDstPicture,
+ pSrc, pMask, pDst);
+
+ return FALSE;
+}
+
+void xorg_composite(struct exa_context *exa,
+ struct exa_pixmap_priv *dst,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height)
+{
+}
+
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.h b/src/gallium/state_trackers/xorg/xorg_composite.h
new file mode 100644
index 0000000000..17dfcb199e
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_composite.h
@@ -0,0 +1,25 @@
+#ifndef XORG_COMPOSITE_H
+#define XORG_COMPOSITE_H
+
+#include "xorg_exa.h"
+
+boolean xorg_composite_accelerated(int op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture);
+
+boolean xorg_composite_bind_state(struct exa_context *exa,
+ int op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture,
+ struct exa_pixmap_priv *pSrc,
+ struct exa_pixmap_priv *pMask,
+ struct exa_pixmap_priv *pDst);
+
+void xorg_composite(struct exa_context *exa,
+ struct exa_pixmap_priv *dst,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height);
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c
index 7304113a65..fe08bde9ef 100644
--- a/src/gallium/state_trackers/xorg/xorg_crtc.c
+++ b/src/gallium/state_trackers/xorg/xorg_crtc.c
@@ -46,13 +46,14 @@
#include <X11/extensions/dpms.h>
#include "pipe/p_inlines.h"
+#include "util/u_rect.h"
struct crtc_private
{
drmModeCrtcPtr drm_crtc;
/* hwcursor */
- struct pipe_buffer *cursor_buf;
+ struct pipe_texture *cursor_tex;
unsigned cursor_handle;
};
@@ -171,11 +172,10 @@ crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
static void
crtc_destroy(xf86CrtcPtr crtc)
{
- modesettingPtr ms = modesettingPTR(crtc->scrn);
struct crtc_private *crtcp = crtc->driver_private;
- if (crtcp->cursor_buf)
- pipe_buffer_reference(&crtcp->cursor_buf, NULL);
+ if (crtcp->cursor_tex)
+ pipe_texture_reference(&crtcp->cursor_tex, NULL);
drmModeFreeCrtc(crtcp->drm_crtc);
xfree(crtcp);
@@ -187,24 +187,42 @@ crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
unsigned char *ptr;
modesettingPtr ms = modesettingPTR(crtc->scrn);
struct crtc_private *crtcp = crtc->driver_private;
-
- if (!crtcp->cursor_buf) {
- crtcp->cursor_buf = pipe_buffer_create(ms->screen,
- 0,
- PIPE_BUFFER_USAGE_CPU_WRITE |
- PIPE_BUFFER_USAGE_GPU_READ,
- 64*64*4);
- drm_api_hooks.handle_from_buffer(ms->screen,
- crtcp->cursor_buf,
- &crtcp->cursor_handle);
+ struct pipe_transfer *transfer;
+
+ if (!crtcp->cursor_tex) {
+ struct pipe_texture templat;
+ unsigned pitch;
+
+ memset(&templat, 0, sizeof(templat));
+ templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
+ templat.target = PIPE_TEXTURE_2D;
+ templat.last_level = 0;
+ templat.depth[0] = 1;
+ templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ templat.width[0] = 64;
+ templat.height[0] = 64;
+ pf_get_block(templat.format, &templat.block);
+
+ crtcp->cursor_tex = ms->screen->texture_create(ms->screen,
+ &templat);
+ ms->api->local_handle_from_texture(ms->api,
+ ms->screen,
+ crtcp->cursor_tex,
+ &pitch,
+ &crtcp->cursor_handle);
}
- ptr = pipe_buffer_map(ms->screen, crtcp->cursor_buf, PIPE_BUFFER_USAGE_CPU_WRITE);
-
- if (ptr)
- memcpy(ptr, image, 64 * 64 * 4);
-
- pipe_buffer_unmap(ms->screen, crtcp->cursor_buf);
+ transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex,
+ 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0, 64, 64);
+ ptr = ms->screen->transfer_map(ms->screen, transfer);
+ util_copy_rect(ptr, &crtcp->cursor_tex->block,
+ transfer->stride, 0, 0,
+ 64, 64, (void*)image, 64 * 4, 0, 0);
+ ms->screen->transfer_unmap(ms->screen, transfer);
+ ms->screen->tex_transfer_destroy(transfer);
}
static void
@@ -222,7 +240,7 @@ crtc_show_cursor(xf86CrtcPtr crtc)
modesettingPtr ms = modesettingPTR(crtc->scrn);
struct crtc_private *crtcp = crtc->driver_private;
- if (crtcp->cursor_buf)
+ if (crtcp->cursor_tex)
drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
crtcp->cursor_handle, 64, 64);
}
@@ -260,13 +278,12 @@ static const xf86CrtcFuncsRec crtc_funcs = {
};
void
-cursor_destroy(xf86CrtcPtr crtc)
+crtc_cursor_destroy(xf86CrtcPtr crtc)
{
- modesettingPtr ms = modesettingPTR(crtc->scrn);
struct crtc_private *crtcp = crtc->driver_private;
- if (crtcp->cursor_buf) {
- pipe_buffer_reference(&crtcp->cursor_buf, NULL);
+ if (crtcp->cursor_tex) {
+ pipe_texture_reference(&crtcp->cursor_tex, NULL);
}
}
diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c
index 401bd39dac..3b90421de9 100644
--- a/src/gallium/state_trackers/xorg/xorg_dri2.c
+++ b/src/gallium/state_trackers/xorg/xorg_dri2.c
@@ -39,10 +39,12 @@
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
+#include "util/u_rect.h"
+
typedef struct {
PixmapPtr pPixmap;
struct pipe_texture *tex;
- struct pipe_buffer *buf;
+ struct pipe_fence_handle *fence;
} *BufferPrivatePtr;
static DRI2BufferPtr
@@ -57,6 +59,7 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
DRI2BufferPtr buffers;
PixmapPtr pPixmap;
unsigned stride, handle;
+ boolean have_depth = FALSE, have_stencil = FALSE;
int i;
buffers = xcalloc(count, sizeof *buffers);
@@ -67,6 +70,16 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
if (!privates)
goto fail_privates;
+ for (i = 0; i < count; i++) {
+ if (attachments[i] == DRI2BufferDepth)
+ have_depth = TRUE;
+ else if (attachments[i] == DRI2BufferStencil)
+ have_stencil = TRUE;
+ }
+
+ if (have_stencil && !have_depth)
+ FatalError("Doesn't support only stencil yet\n");
+
depth = NULL;
for (i = 0; i < count; i++) {
pPixmap = NULL;
@@ -78,38 +91,48 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
else
pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw);
pPixmap->refcnt++;
- tex = xorg_exa_get_texture(pPixmap);
} else if (attachments[i] == DRI2BufferStencil) {
pipe_texture_reference(&tex, depth);
} else if (attachments[i] == DRI2BufferDepth) {
struct pipe_texture template;
-
memset(&template, 0, sizeof(template));
template.target = PIPE_TEXTURE_2D;
- template.format = PIPE_FORMAT_S8Z24_UNORM;
+ if (have_stencil)
+ template.format = ms->ds_depth_bits_last ?
+ PIPE_FORMAT_S8Z24_UNORM : PIPE_FORMAT_Z24S8_UNORM;
+ else
+ template.format = ms->d_depth_bits_last ?
+ PIPE_FORMAT_X8Z24_UNORM : PIPE_FORMAT_Z24X8_UNORM;
pf_get_block(template.format, &template.block);
template.width[0] = pDraw->width;
template.height[0] = pDraw->height;
template.depth[0] = 1;
template.last_level = 0;
- template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
tex = ms->screen->texture_create(ms->screen, &template);
+ depth = tex;
+ } else if (attachments[i] == DRI2BufferFakeFrontLeft &&
+ pDraw->type == DRAWABLE_PIXMAP) {
+ pPixmap = (PixmapPtr) pDraw;
+ pPixmap->refcnt++;
} else {
- struct pipe_texture template;
- memset(&template, 0, sizeof(template));
- template.target = PIPE_TEXTURE_2D;
- template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
- pf_get_block(template.format, &template.block);
- template.width[0] = pDraw->width;
- template.height[0] = pDraw->height;
- template.depth[0] = 1;
- template.last_level = 0;
- template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
- tex = ms->screen->texture_create(ms->screen, &template);
+ pPixmap = (*pScreen->CreatePixmap)(pScreen, pDraw->width,
+ pDraw->height,
+ pDraw->depth,
+ 0);
+ }
+
+ if (pPixmap) {
+ xorg_exa_set_shared_usage(pPixmap);
+ pScreen->ModifyPixmapHeader(pPixmap, 0, 0, 0, 0, 0, NULL);
+ tex = xorg_exa_get_texture(pPixmap);
}
- drm_api_hooks.buffer_from_texture(tex, &buf, &stride);
- drm_api_hooks.global_handle_from_buffer(ms->screen, buf, &handle);
+ if (!tex)
+ FatalError("NO TEXTURE IN DRI2\n");
+
+ ms->api->shared_handle_from_texture(ms->api, ms->screen, tex, &stride, &handle);
buffers[i].name = handle;
buffers[i].attachment = attachments[i];
@@ -118,7 +141,6 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
buffers[i].driverPrivate = &privates[i];
buffers[i].flags = 0; /* not tiled */
privates[i].pPixmap = pPixmap;
- privates[i].buf = buf;
privates[i].tex = tex;
}
@@ -138,15 +160,16 @@ driDestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count)
modesettingPtr ms = modesettingPTR(pScrn);
BufferPrivatePtr private;
int i;
+ (void)ms;
for (i = 0; i < count; i++) {
private = buffers[i].driverPrivate;
+ pipe_texture_reference(&private->tex, NULL);
+ ms->screen->fence_reference(ms->screen, &private->fence, NULL);
+
if (private->pPixmap)
(*pScreen->DestroyPixmap)(private->pPixmap);
-
- pipe_texture_reference(&private->tex, NULL);
- pipe_buffer_reference(&private->buf, NULL);
}
if (buffers) {
@@ -164,19 +187,83 @@ driCopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
modesettingPtr ms = modesettingPTR(pScrn);
BufferPrivatePtr dst_priv = pDestBuffer->driverPrivate;
BufferPrivatePtr src_priv = pSrcBuffer->driverPrivate;
+ PixmapPtr src_pixmap;
+ PixmapPtr dst_pixmap;
+ GCPtr gc;
+ RegionPtr copy_clip;
+
+ /*
+ * In driCreateBuffers we dewrap windows into the
+ * backing pixmaps in order to get to the texture.
+ * We need to use the real drawable in CopyArea
+ * so that cliprects and offsets are correct.
+ */
+ src_pixmap = src_priv->pPixmap;
+ dst_pixmap = dst_priv->pPixmap;
+ if (pSrcBuffer->attachment == DRI2BufferFrontLeft)
+ src_pixmap = (PixmapPtr)pDraw;
+ if (pDestBuffer->attachment == DRI2BufferFrontLeft)
+ dst_pixmap = (PixmapPtr)pDraw;
+
+ /*
+ * The clients implements glXWaitX with a copy front to fake and then
+ * waiting on the server to signal its completion of it. While
+ * glXWaitGL is a client side flush and a copy from fake to front.
+ * This is how it is done in the DRI2 protocol, how ever depending
+ * which type of drawables the server does things a bit differently
+ * then what the protocol says as the fake and front are the same.
+ *
+ * for pixmaps glXWaitX is a server flush.
+ * for pixmaps glXWaitGL is a client flush.
+ * for windows glXWaitX is a copy from front to fake then a server flush.
+ * for windows glXWaitGL is a client flush then a copy from fake to front.
+ *
+ * XXX in the windows case this code always flushes but that isn't a
+ * must in the glXWaitGL case but we don't know if this is a glXWaitGL
+ * or a glFlush/glFinish call.
+ */
+ if (dst_pixmap == src_pixmap) {
+ /* pixmap glXWaitX */
+ if (pSrcBuffer->attachment == DRI2BufferFrontLeft &&
+ pDestBuffer->attachment == DRI2BufferFakeFrontLeft) {
+ ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS, NULL);
+ return;
+ }
+ /* pixmap glXWaitGL */
+ if (pDestBuffer->attachment == DRI2BufferFrontLeft &&
+ pSrcBuffer->attachment == DRI2BufferFakeFrontLeft) {
+ return;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "copying between the same pixmap\n");
+ }
+ }
+
+ gc = GetScratchGC(pDraw->depth, pScreen);
+ copy_clip = REGION_CREATE(pScreen, NULL, 0);
+ REGION_COPY(pScreen, copy_clip, pRegion);
+ (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
+ ValidateGC(&dst_pixmap->drawable, gc);
+
+ /* If this is a full buffer swap, throttle on the previous one */
+ if (dst_priv->fence && REGION_NUM_RECTS(pRegion) == 1) {
+ BoxPtr extents = REGION_EXTENTS(pScreen, pRegion);
- struct pipe_surface *dst_surf =
- ms->screen->get_tex_surface(ms->screen, dst_priv->tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_WRITE);
- struct pipe_surface *src_surf =
- ms->screen->get_tex_surface(ms->screen, src_priv->tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ);
+ if (extents->x1 == 0 && extents->y1 == 0 &&
+ extents->x2 == pDraw->width && extents->y2 == pDraw->height) {
+ ms->screen->fence_finish(ms->screen, dst_priv->fence, 0);
+ ms->screen->fence_reference(ms->screen, &dst_priv->fence, NULL);
+ }
+ }
+
+ (*gc->ops->CopyArea)(&src_pixmap->drawable, &dst_pixmap->drawable, gc,
+ 0, 0, pDraw->width, pDraw->height, 0, 0);
- ms->ctx->surface_copy(ms->ctx, dst_surf, 0, 0, src_surf,
- 0, 0, pDraw->width, pDraw->height);
+ FreeScratchGC(gc);
- pipe_surface_reference(&dst_surf, NULL);
- pipe_surface_reference(&src_surf, NULL);
+ ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS,
+ pDestBuffer->attachment == DRI2BufferFrontLeft ?
+ &dst_priv->fence : NULL);
}
Bool
@@ -188,17 +275,23 @@ driScreenInit(ScreenPtr pScreen)
dri2info.version = 1;
dri2info.fd = ms->fd;
-#if 0
- dri2info.driverName = pScrn->name;
-#else
- dri2info.driverName = "i915"; /* FIXME */
-#endif
+
+ dri2info.driverName = pScrn->driverName;
dri2info.deviceName = "/dev/dri/card0"; /* FIXME */
dri2info.CreateBuffers = driCreateBuffers;
dri2info.DestroyBuffers = driDestroyBuffers;
dri2info.CopyRegion = driCopyRegion;
+ ms->d_depth_bits_last =
+ ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_X8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+ ms->ds_depth_bits_last =
+ ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+
return DRI2ScreenInit(pScreen, &dri2info);
}
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c
index 45e831f0c2..bc3fd54bdb 100644
--- a/src/gallium/state_trackers/xorg/xorg_driver.c
+++ b/src/gallium/state_trackers/xorg/xorg_driver.c
@@ -54,6 +54,7 @@
#include <pciaccess.h>
+#include "pipe/p_context.h"
#include "xorg_tracker.h"
#include "xorg_winsys.h"
@@ -179,8 +180,10 @@ CreateFrontBuffer(ScrnInfoPtr pScrn)
modesettingPtr ms = modesettingPTR(pScrn);
ScreenPtr pScreen = pScrn->pScreen;
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ unsigned handle, stride;
ms->noEvict = TRUE;
+ xorg_exa_set_displayed_usage(rootPixmap);
pScreen->ModifyPixmapHeader(rootPixmap,
pScrn->virtualX, pScrn->virtualY,
pScrn->depth, pScrn->bitsPerPixel,
@@ -188,13 +191,16 @@ CreateFrontBuffer(ScrnInfoPtr pScrn)
NULL);
ms->noEvict = FALSE;
+ handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
+
drmModeAddFB(ms->fd,
pScrn->virtualX,
pScrn->virtualY,
pScrn->depth,
pScrn->bitsPerPixel,
- pScrn->displayWidth * pScrn->bitsPerPixel / 8,
- xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id);
+ stride,
+ handle,
+ &ms->fb_id);
pScrn->frameX0 = 0;
pScrn->frameY0 = 0;
@@ -300,6 +306,7 @@ PreInit(ScrnInfoPtr pScrn, int flags)
ms->PciInfo->dev, ms->PciInfo->func
);
+ ms->api = drm_api_create();
ms->fd = drmOpen(NULL, BusID);
if (ms->fd < 0)
@@ -418,6 +425,44 @@ RestoreHWState(ScrnInfoPtr pScrn)
return TRUE;
}
+static void xorgBlockHandler(int i, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]);
+
+ pScreen->BlockHandler = ms->blockHandler;
+ pScreen->BlockHandler(i, blockData, pTimeout, pReadmask);
+ pScreen->BlockHandler = xorgBlockHandler;
+
+ ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ {
+ RegionPtr dirty = DamageRegion(ms->damage);
+ unsigned num_cliprects = REGION_NUM_RECTS(dirty);
+
+ if (num_cliprects) {
+ drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip));
+ BoxPtr rect = REGION_RECTS(dirty);
+ int i;
+
+ for (i = 0; i < num_cliprects; i++, rect++) {
+ clip[i].x = rect->x1;
+ clip[i].y = rect->y1;
+ clip[i].width = rect->x2 - rect->x1;
+ clip[i].height = rect->y2 - rect->y1;
+ }
+
+ /* TODO query connector property to see if this is needed */
+ drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects);
+
+ DamageEmpty(ms->damage);
+ }
+ }
+#endif
+}
+
static Bool
CreateScreenResources(ScreenPtr pScreen)
{
@@ -425,6 +470,7 @@ CreateScreenResources(ScreenPtr pScreen)
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap;
Bool ret;
+ unsigned handle, stride;
ms->noEvict = TRUE;
@@ -434,21 +480,41 @@ CreateScreenResources(ScreenPtr pScreen)
rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ xorg_exa_set_displayed_usage(rootPixmap);
+ xorg_exa_set_shared_usage(rootPixmap);
if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
FatalError("Couldn't adjust screen pixmap\n");
ms->noEvict = FALSE;
+ handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
+
drmModeAddFB(ms->fd,
pScrn->virtualX,
pScrn->virtualY,
pScrn->depth,
pScrn->bitsPerPixel,
- pScrn->displayWidth * pScrn->bitsPerPixel / 8,
- xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id);
+ stride,
+ handle,
+ &ms->fb_id);
AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
+ pScreen, rootPixmap);
+
+ if (ms->damage) {
+ DamageRegister(&rootPixmap->drawable, ms->damage);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to create screen damage record\n");
+ return FALSE;
+ }
+#endif
+
return ret;
}
@@ -476,7 +542,7 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
}
if (!ms->screen) {
- ms->screen = drm_api_hooks.create_screen(ms->fd, NULL);
+ ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL);
if (!ms->screen) {
FatalError("Could not init pipe_screen\n");
@@ -525,6 +591,8 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
fbPictureInit(pScreen, NULL, 0);
+ ms->blockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = xorgBlockHandler;
ms->createScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = CreateScreenResources;
@@ -593,10 +661,6 @@ FreeScreen(int scrnIndex, int flags)
FreeRec(xf86Screens[scrnIndex]);
}
-/* HACK */
-void
-cursor_destroy(xf86CrtcPtr crtc);
-
static void
LeaveVT(int scrnIndex, int flags)
{
@@ -608,7 +672,7 @@ LeaveVT(int scrnIndex, int flags)
for (o = 0; o < config->num_crtc; o++) {
xf86CrtcPtr crtc = config->crtc[o];
- cursor_destroy(crtc);
+ crtc_cursor_destroy(crtc);
if (crtc->rotatedPixmap || crtc->rotatedData) {
crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
@@ -622,6 +686,10 @@ LeaveVT(int scrnIndex, int flags)
RestoreHWState(pScrn);
+ if (drmDropMaster(ms->fd))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmDropMaster failed: %s\n", strerror(errno));
+
pScrn->vtSema = FALSE;
}
@@ -634,6 +702,17 @@ EnterVT(int scrnIndex, int flags)
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
modesettingPtr ms = modesettingPTR(pScrn);
+ if (drmSetMaster(ms->fd)) {
+ if (errno == EINVAL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmSetMaster failed: 2.6.29 or newer kernel required for "
+ "multi-server DRI\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmSetMaster failed: %s\n", strerror(errno));
+ }
+ }
+
/*
* Only save state once per server generation since that's what most
* drivers do. Could change this to save state at each VT enter.
@@ -673,11 +752,22 @@ CloseScreen(int scrnIndex, ScreenPtr pScreen)
driCloseScreen(pScreen);
#endif
+ pScreen->BlockHandler = ms->blockHandler;
pScreen->CreateScreenResources = ms->createScreenResources;
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ if (ms->damage) {
+ DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
+ DamageDestroy(ms->damage);
+ ms->damage = NULL;
+ }
+#endif
+
if (ms->exa)
xorg_exa_close(pScrn);
+ ms->api->destroy(ms->api);
+ ms->api = NULL;
drmClose(ms->fd);
ms->fd = -1;
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index 7913174354..18afa01dbd 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -28,34 +28,24 @@
*
*/
-#include "xorg-server.h"
-#include "xf86.h"
+#include "xorg_exa.h"
#include "xorg_tracker.h"
+#include "xorg_composite.h"
+#include "xorg_exa_tgsi.h"
+
+#include <xorg-server.h>
+#include <xf86.h>
+#include <picturestr.h>
+#include <picture.h>
#include "pipe/p_format.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
-#include "util/u_rect.h"
-
-struct exa_entity
-{
- ExaDriverPtr pExa;
- struct pipe_context *ctx;
- struct pipe_screen *scrn;
-};
-
-struct PixmapPriv
-{
- int flags;
- struct pipe_texture *tex;
- unsigned int color;
- struct pipe_surface *src_surf; /* for copies */
+#include "cso_cache/cso_context.h"
- struct pipe_transfer *map_transfer;
- unsigned map_count;
-};
+#include "util/u_rect.h"
/*
* Helper functions
@@ -113,8 +103,8 @@ ExaPrepareAccess(PixmapPtr pPix, int index)
ScreenPtr pScreen = pPix->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_entity *exa = ms->exa;
- struct PixmapPriv *priv;
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv;
priv = exaGetPixmapDriverPrivate(pPix);
@@ -126,6 +116,10 @@ ExaPrepareAccess(PixmapPtr pPix, int index)
if (priv->map_count++ == 0)
{
+ if (exa->ctx->is_texture_referenced(exa->ctx, priv->tex, 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE)
+ exa->ctx->flush(exa->ctx, 0, NULL);
+
priv->map_transfer =
exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
PIPE_TRANSFER_READ_WRITE,
@@ -145,8 +139,8 @@ ExaFinishAccess(PixmapPtr pPix, int index)
ScreenPtr pScreen = pPix->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_entity *exa = ms->exa;
- struct PixmapPriv *priv;
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv;
priv = exaGetPixmapDriverPrivate(pPix);
if (!priv)
@@ -160,6 +154,7 @@ ExaFinishAccess(PixmapPtr pPix, int index)
exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
exa->scrn->tex_transfer_destroy(priv->map_transfer);
priv->map_transfer = NULL;
+ pPix->devPrivate.ptr = NULL;
}
}
@@ -168,8 +163,8 @@ ExaDone(PixmapPtr pPixmap)
{
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
- struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
- struct exa_entity *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ struct exa_context *exa = ms->exa;
if (!priv)
return;
@@ -190,8 +185,8 @@ ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
{
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
- struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
- struct exa_entity *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ struct exa_context *exa = ms->exa;
if (1)
return FALSE;
@@ -221,12 +216,9 @@ ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
{
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_entity *exa = ms->exa;
- struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
- struct pipe_surface *surf =
- exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ struct pipe_surface *surf = exa_gpu_surface(exa, priv);
exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0,
priv->color);
@@ -240,12 +232,9 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
{
ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_entity *exa = ms->exa;
- struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
- struct PixmapPriv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
-
- if (1)
- return FALSE;
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+ struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
if (alu != GXcopy)
return FALSE;
@@ -265,10 +254,7 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
if (!exa->ctx || !exa->ctx->surface_copy)
return FALSE;
- priv->src_surf =
- exa->scrn->get_tex_surface(exa->scrn, src_priv->tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
+ priv->src_surf = exa_gpu_surface(exa, src_priv);
return TRUE;
}
@@ -279,12 +265,9 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
{
ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_entity *exa = ms->exa;
- struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
- struct pipe_surface *surf =
- exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+ struct pipe_surface *surf = exa_gpu_surface(exa, priv);
exa->ctx->surface_copy(exa->ctx, surf, dstX, dstY, priv->src_surf,
srcX, srcY, width, height);
@@ -296,13 +279,28 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
PicturePtr pMaskPicture, PicturePtr pDstPicture,
PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
{
- return FALSE;
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+
+ return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
+ pDstPicture,
+ exaGetPixmapDriverPrivate(pSrc),
+ exaGetPixmapDriverPrivate(pMask),
+ exaGetPixmapDriverPrivate(pDst));
}
static void
ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height)
{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
+
+ xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
+ dstX, dstY, width, height);
}
static Bool
@@ -310,15 +308,18 @@ ExaCheckComposite(int op,
PicturePtr pSrcPicture, PicturePtr pMaskPicture,
PicturePtr pDstPicture)
{
- return FALSE;
+ return xorg_composite_accelerated(op,
+ pSrcPicture,
+ pMaskPicture,
+ pDstPicture);
}
static void *
ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
{
- struct PixmapPriv *priv;
+ struct exa_pixmap_priv *priv;
- priv = xcalloc(1, sizeof(struct PixmapPriv));
+ priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
if (!priv)
return NULL;
@@ -328,7 +329,7 @@ ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
static void
ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
{
- struct PixmapPriv *priv = (struct PixmapPriv *)dPriv;
+ struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
@@ -344,7 +345,7 @@ ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
static Bool
ExaPixmapIsOffscreen(PixmapPtr pPixmap)
{
- struct PixmapPriv *priv;
+ struct exa_pixmap_priv *priv;
priv = exaGetPixmapDriverPrivate(pPixmap);
@@ -357,14 +358,45 @@ ExaPixmapIsOffscreen(PixmapPtr pPixmap)
return FALSE;
}
+int
+xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
+{
+ struct exa_pixmap_priv *priv;
+ priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!priv) {
+ FatalError("NO PIXMAP PRIVATE\n");
+ return 0;
+ }
+
+ priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
+
+ return 0;
+}
+
+int
+xorg_exa_set_shared_usage(PixmapPtr pPixmap)
+{
+ struct exa_pixmap_priv *priv;
+ priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!priv) {
+ FatalError("NO PIXMAP PRIVATE\n");
+ return 0;
+ }
+
+ priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
+ return 0;
+}
+
unsigned
-xorg_exa_get_pixmap_handle(PixmapPtr pPixmap)
+xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
- struct PixmapPriv *priv;
- struct pipe_buffer *buffer = NULL;
+ struct exa_pixmap_priv *priv;
unsigned handle;
unsigned stride;
@@ -380,9 +412,10 @@ xorg_exa_get_pixmap_handle(PixmapPtr pPixmap)
return 0;
}
- drm_api_hooks.buffer_from_texture(priv->tex, &buffer, &stride);
- drm_api_hooks.handle_from_buffer(ms->screen, buffer, &handle);
- pipe_buffer_reference(&buffer, NULL);
+ ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
+ if (stride_out)
+ *stride_out = stride;
+
return handle;
}
@@ -393,9 +426,9 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_entity *exa = ms->exa;
+ struct exa_context *exa = ms->exa;
if (!priv)
return FALSE;
@@ -419,11 +452,17 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
bitsPerPixel, devKind, NULL);
/* Deal with screen resize */
- if (priv->tex && (priv->tex->width[0] != width || priv->tex->height[0] != height)) {
+ if (priv->tex && (priv->tex->width[0] != width ||
+ priv->tex->height[0] != height ||
+ priv->tex_flags != priv->flags)) {
pipe_texture_reference(&priv->tex, NULL);
}
- if (!priv->tex) {
+ if (!priv->tex
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ && priv->flags
+#endif
+ ) {
struct pipe_texture template;
memset(&template, 0, sizeof(template));
@@ -434,20 +473,44 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
template.height[0] = height;
template.depth[0] = 1;
template.last_level = 0;
- template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
+ priv->tex_flags = priv->flags;
priv->tex = exa->scrn->texture_create(exa->scrn, &template);
}
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ if (!priv->tex) {
+ if (pPixData)
+ pPixmap->devPrivate.ptr = pPixData;
+ else
+ pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height * pPixmap->devKind);
+ } else
+#endif
if (pPixData) {
struct pipe_transfer *transfer =
exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
PIPE_TRANSFER_WRITE,
0, 0, width, height);
- pipe_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
+ util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
&priv->tex->block, transfer->stride, 0, 0,
width, height, pPixData, pPixmap->devKind, 0, 0);
exa->scrn->transfer_unmap(exa->scrn, transfer);
exa->scrn->tex_transfer_destroy(transfer);
+ } else if (priv->tex && pPixmap->devPrivate.ptr) {
+ struct pipe_transfer *transfer;
+
+ if (priv->map_count != 0)
+ FatalError("doing ExaModifyPixmapHeader on mapped buffer\n");
+
+ transfer =
+ exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0, width, height);
+ util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
+ &priv->tex->block, transfer->stride, 0, 0,
+ width, height, pPixmap->devPrivate.ptr, pPixmap->devKind, 0, 0);
+ exa->scrn->transfer_unmap(exa->scrn, transfer);
+ exa->scrn->tex_transfer_destroy(transfer);
}
return TRUE;
@@ -456,87 +519,117 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
struct pipe_texture *
xorg_exa_get_texture(PixmapPtr pPixmap)
{
- struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
- struct pipe_texture *tex = NULL;
- pipe_texture_reference(&tex, priv->tex);
- return tex;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ struct pipe_texture *tex = NULL;
+ pipe_texture_reference(&tex, priv->tex);
+ return tex;
}
void
xorg_exa_close(ScrnInfoPtr pScrn)
{
- modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_entity *exa = ms->exa;
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer;
+ struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer;
- if (exa->ctx)
- exa->ctx->destroy(exa->ctx);
+ if (exa->shaders) {
+ xorg_shaders_destroy(exa->shaders);
+ }
- exaDriverFini(pScrn->pScreen);
- xfree(exa);
- ms->exa = NULL;
-}
+ if (vsbuf && vsbuf->buffer)
+ pipe_buffer_reference(&vsbuf->buffer, NULL);
-void *
-xorg_exa_init(ScrnInfoPtr pScrn)
-{
- modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_entity *exa;
- ExaDriverPtr pExa;
+ if (fsbuf && fsbuf->buffer)
+ pipe_buffer_reference(&fsbuf->buffer, NULL);
- exa = xcalloc(1, sizeof(struct exa_entity));
- if (!exa)
- return NULL;
+ if (exa->cso) {
+ cso_release_all(exa->cso);
+ cso_destroy_context(exa->cso);
+ }
- pExa = exaDriverAlloc();
- if (!pExa) {
- goto out_err;
- }
+ if (exa->ctx)
+ exa->ctx->destroy(exa->ctx);
- memset(pExa, 0, sizeof(*pExa));
- pExa->exa_major = 2;
- pExa->exa_minor = 2;
- pExa->memoryBase = 0;
- pExa->memorySize = 0;
- pExa->offScreenBase = 0;
- pExa->pixmapOffsetAlign = 0;
- pExa->pixmapPitchAlign = 1;
- pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
- pExa->maxX = 8191; /* FIXME */
- pExa->maxY = 8191; /* FIXME */
- pExa->WaitMarker = ExaWaitMarker;
- pExa->MarkSync = ExaMarkSync;
- pExa->PrepareSolid = ExaPrepareSolid;
- pExa->Solid = ExaSolid;
- pExa->DoneSolid = ExaDone;
- pExa->PrepareCopy = ExaPrepareCopy;
- pExa->Copy = ExaCopy;
- pExa->DoneCopy = ExaDone;
- pExa->CheckComposite = ExaCheckComposite;
- pExa->PrepareComposite = ExaPrepareComposite;
- pExa->Composite = ExaComposite;
- pExa->DoneComposite = ExaDoneComposite;
- pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
- pExa->PrepareAccess = ExaPrepareAccess;
- pExa->FinishAccess = ExaFinishAccess;
- pExa->CreatePixmap = ExaCreatePixmap;
- pExa->DestroyPixmap = ExaDestroyPixmap;
- pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
-
- if (!exaDriverInit(pScrn->pScreen, pExa)) {
- goto out_err;
- }
-
- exa->scrn = ms->screen;
- exa->ctx = drm_api_hooks.create_context(exa->scrn);
- /* Share context with DRI */
- ms->ctx = exa->ctx;
+ exaDriverFini(pScrn->pScreen);
+ xfree(exa);
+ ms->exa = NULL;
+}
- return (void *)exa;
+void *
+xorg_exa_init(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa;
+ ExaDriverPtr pExa;
+
+ exa = xcalloc(1, sizeof(struct exa_context));
+ if (!exa)
+ return NULL;
+
+ pExa = exaDriverAlloc();
+ if (!pExa) {
+ goto out_err;
+ }
+
+ memset(pExa, 0, sizeof(*pExa));
+
+ pExa->exa_major = 2;
+ pExa->exa_minor = 2;
+ pExa->memoryBase = 0;
+ pExa->memorySize = 0;
+ pExa->offScreenBase = 0;
+ pExa->pixmapOffsetAlign = 0;
+ pExa->pixmapPitchAlign = 1;
+ pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
+ pExa->maxX = 8191; /* FIXME */
+ pExa->maxY = 8191; /* FIXME */
+
+ pExa->WaitMarker = ExaWaitMarker;
+ pExa->MarkSync = ExaMarkSync;
+ pExa->PrepareSolid = ExaPrepareSolid;
+ pExa->Solid = ExaSolid;
+ pExa->DoneSolid = ExaDone;
+ pExa->PrepareCopy = ExaPrepareCopy;
+ pExa->Copy = ExaCopy;
+ pExa->DoneCopy = ExaDone;
+ pExa->CheckComposite = ExaCheckComposite;
+ pExa->PrepareComposite = ExaPrepareComposite;
+ pExa->Composite = ExaComposite;
+ pExa->DoneComposite = ExaDoneComposite;
+ pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
+ pExa->PrepareAccess = ExaPrepareAccess;
+ pExa->FinishAccess = ExaFinishAccess;
+ pExa->CreatePixmap = ExaCreatePixmap;
+ pExa->DestroyPixmap = ExaDestroyPixmap;
+ pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
+
+ if (!exaDriverInit(pScrn->pScreen, pExa)) {
+ goto out_err;
+ }
+
+ exa->scrn = ms->screen;
+ exa->ctx = ms->api->create_context(ms->api, exa->scrn);
+ /* Share context with DRI */
+ ms->ctx = exa->ctx;
+
+ exa->cso = cso_create_context(exa->ctx);
+ exa->shaders = xorg_shaders_create(exa);
+
+ return (void *)exa;
+
+out_err:
+ xorg_exa_close(pScrn);
+
+ return NULL;
+}
- out_err:
- xorg_exa_close(pScrn);
+struct pipe_surface *
+exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
+{
+ return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
- return NULL;
}
-/* vim: set sw=4 ts=8 sts=4: */
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h
new file mode 100644
index 0000000000..0a93fa0bd7
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_exa.h
@@ -0,0 +1,41 @@
+#ifndef XORG_EXA_H
+#define XORG_EXA_H
+
+#include "xorg_tracker.h"
+
+#include <pipe/p_state.h>
+
+struct cso_context;
+struct xorg_shaders;
+
+struct exa_context
+{
+ ExaDriverPtr pExa;
+ struct pipe_context *ctx;
+ struct pipe_screen *scrn;
+ struct cso_context *cso;
+ struct xorg_shaders *shaders;
+
+ struct pipe_constant_buffer vs_const_buffer;
+ struct pipe_constant_buffer fs_const_buffer;
+};
+
+
+struct exa_pixmap_priv
+{
+ int flags;
+ int tex_flags;
+
+ struct pipe_texture *tex;
+ unsigned int color;
+ struct pipe_surface *src_surf; /* for copies */
+
+ struct pipe_transfer *map_transfer;
+ unsigned map_count;
+};
+
+struct pipe_surface *
+exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv);
+
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
new file mode 100644
index 0000000000..b5288bde4f
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
@@ -0,0 +1,259 @@
+#include "xorg_exa_tgsi.h"
+
+/*### stupidity defined in X11/extensions/XI.h */
+#undef Absolute
+
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_memory.h"
+#include "util/u_simple_shaders.h"
+
+#include "tgsi/tgsi_ureg.h"
+
+#include "cso_cache/cso_context.h"
+#include "cso_cache/cso_hash.h"
+
+/* Vertex shader:
+ * IN[0] = src_pos
+ * IN[1] = mask_pos
+ * IN[2] = dst_pos
+ * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
+ * CONST[1] = (-1, -1, 0, 0)
+ *
+ * OUT[0] = src_pos
+ * OUT[1] = mask_pos
+ * OUT[2] = dst_pos
+ */
+
+/* Fragment shader:
+ * SAMP[0] = src
+ * SAMP[1] = mask
+ * SAMP[2] = dst
+ * IN[0] = pos src
+ * IN[1] = pos mask
+ * IN[2] = pos dst
+ * CONST[0] = (0, 0, 0, 1)
+ *
+ * OUT[0] = color
+ */
+
+struct xorg_shaders {
+ struct exa_context *exa;
+
+ struct cso_hash *vs_hash;
+ struct cso_hash *fs_hash;
+};
+
+static const char over_op[] =
+ "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n"
+ "MUL TEMP[3], TEMP[0], TEMP[3]\n"
+ "ADD TEMP[0], TEMP[3], TEMP[0]\n";
+
+
+static INLINE void
+create_preamble(struct ureg_program *ureg)
+{
+}
+
+
+static INLINE void
+src_in_mask(struct ureg_program *ureg,
+ struct ureg_dst dst,
+ struct ureg_src src,
+ struct ureg_src mask)
+{
+ /* MUL dst, src, mask.wwww */
+ ureg_MUL(ureg, dst, src,
+ ureg_scalar(mask, TGSI_SWIZZLE_W));
+}
+
+static struct ureg_src
+vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords,
+ struct ureg_src const0, struct ureg_src const1)
+{
+ struct ureg_dst tmp = ureg_DECL_temporary(ureg);
+ struct ureg_src ret;
+ ureg_MUL(ureg, tmp, coords, const0);
+ ureg_ADD(ureg, tmp, ureg_src(tmp), const1);
+ ret = ureg_src(tmp);
+ ureg_release_temporary(ureg, tmp);
+ return ret;
+}
+
+static void *
+create_vs(struct pipe_context *pipe,
+ unsigned vs_traits)
+{
+ struct ureg_program *ureg;
+ struct ureg_src src;
+ struct ureg_dst dst;
+ struct ureg_src const0, const1;
+
+ ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+ if (ureg == NULL)
+ return 0;
+
+ const0 = ureg_DECL_constant(ureg);
+ const1 = ureg_DECL_constant(ureg);
+
+ if ((vs_traits & VS_COMPOSITE)) {
+ src = ureg_DECL_vs_input(ureg,
+ TGSI_SEMANTIC_POSITION, 0);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+ src = vs_normalize_coords(ureg, src,
+ const0, const1);
+ ureg_MOV(ureg, dst, src);
+ }
+ if ((vs_traits & VS_MASK)) {
+ src = ureg_DECL_vs_input(ureg,
+ TGSI_SEMANTIC_POSITION, 1);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 1);
+ ureg_MOV(ureg, dst, src);
+ }
+
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+static void *
+create_fs(struct pipe_context *pipe,
+ unsigned fs_traits)
+{
+ struct ureg_program *ureg;
+ struct ureg_src dst_sampler, src_sampler, mask_sampler;
+ struct ureg_src dst_pos, src_pos, mask_pos;
+ struct ureg_src src, mask;
+ struct ureg_dst out;
+
+ ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+ if (ureg == NULL)
+ return 0;
+
+ out = ureg_DECL_output(ureg,
+ TGSI_SEMANTIC_COLOR,
+ 0);
+
+ src_sampler = ureg_DECL_sampler(ureg);
+ src_pos = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_POSITION,
+ 0,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+
+ if ((fs_traits & FS_MASK)) {
+ mask_sampler = ureg_DECL_sampler(ureg);
+ mask_pos = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_POSITION,
+ 1,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+ }
+
+#if 0 /* unused right now */
+ dst_sampler = ureg_DECL_sampler(ureg);
+ dst_pos = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_POSITION,
+ 2,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+#endif
+
+ if ((fs_traits & FS_MASK)) {
+ ureg_TEX(ureg, ureg_dst(mask),
+ TGSI_TEXTURE_2D, mask_pos, mask_sampler);
+ /* src IN mask */
+ src_in_mask(ureg, out, src, mask);
+ } else {
+ ureg_TEX(ureg, out,
+ TGSI_TEXTURE_2D, src_pos, src_sampler);
+ }
+
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+struct xorg_shaders * xorg_shaders_create(struct exa_context *exa)
+{
+ struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders);
+
+ sc->exa = exa;
+ sc->vs_hash = cso_hash_create();
+ sc->fs_hash = cso_hash_create();
+
+ return sc;
+}
+
+static void
+cache_destroy(struct cso_context *cso,
+ struct cso_hash *hash,
+ unsigned processor)
+{
+ struct cso_hash_iter iter = cso_hash_first_node(hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ void *shader = (void *)cso_hash_iter_data(iter);
+ if (processor == PIPE_SHADER_FRAGMENT) {
+ cso_delete_fragment_shader(cso, shader);
+ } else if (processor == PIPE_SHADER_VERTEX) {
+ cso_delete_vertex_shader(cso, shader);
+ }
+ iter = cso_hash_erase(hash, iter);
+ }
+ cso_hash_delete(hash);
+}
+
+void xorg_shaders_destroy(struct xorg_shaders *sc)
+{
+ cache_destroy(sc->exa->cso, sc->vs_hash,
+ PIPE_SHADER_VERTEX);
+ cache_destroy(sc->exa->cso, sc->fs_hash,
+ PIPE_SHADER_FRAGMENT);
+
+ free(sc);
+}
+
+static INLINE void *
+shader_from_cache(struct pipe_context *pipe,
+ unsigned type,
+ struct cso_hash *hash,
+ unsigned key)
+{
+ void *shader = 0;
+
+ struct cso_hash_iter iter = cso_hash_find(hash, key);
+
+ if (cso_hash_iter_is_null(iter)) {
+ if (type == PIPE_SHADER_VERTEX)
+ shader = create_vs(pipe, key);
+ else
+ shader = create_fs(pipe, key);
+ cso_hash_insert(hash, key, shader);
+ } else
+ shader = (void *)cso_hash_iter_data(iter);
+
+ return shader;
+}
+
+struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
+ unsigned vs_traits,
+ unsigned fs_traits)
+{
+ struct xorg_shader shader = {0};
+ void *vs, *fs;
+
+ vs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_VERTEX,
+ sc->vs_hash, vs_traits);
+ fs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_FRAGMENT,
+ sc->fs_hash, fs_traits);
+
+ debug_assert(vs && fs);
+ if (!vs || !fs)
+ return shader;
+
+ shader.vs = vs;
+ shader.fs = fs;
+
+ return shader;
+}
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
new file mode 100644
index 0000000000..003e5d8caf
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
@@ -0,0 +1,35 @@
+#ifndef XORG_EXA_TGSI_H
+#define XORG_EXA_TGSI_H
+
+#include "xorg_exa.h"
+
+enum xorg_vs_traits {
+ VS_COMPOSITE = 1 << 0,
+ VS_MASK = 1 << 1,
+ VS_FILL = 1 << 2
+ /*VS_TRANSFORM = 1 << 3*/
+};
+
+enum xorg_fs_traits {
+ FS_COMPOSITE = 1 << 0,
+ FS_MASK = 1 << 1,
+ FS_FILL = 1 << 2,
+ FS_LINEAR_GRADIENT = 1 << 3,
+ FS_RADIAL_GRADIENT = 1 << 4
+};
+
+struct xorg_shader {
+ void *fs;
+ void *vs;
+};
+
+struct xorg_shaders;
+
+struct xorg_shaders *xorg_shaders_create(struct exa_context *exa);
+void xorg_shaders_destroy(struct xorg_shaders *shaders);
+
+struct xorg_shader xorg_shaders_get(struct xorg_shaders *shaders,
+ unsigned vs_traits,
+ unsigned fs_traits);
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h
index 82c3890dfb..b1ab783a15 100644
--- a/src/gallium/state_trackers/xorg/xorg_tracker.h
+++ b/src/gallium/state_trackers/xorg/xorg_tracker.h
@@ -31,11 +31,20 @@
#ifndef _XORG_TRACKER_H_
#define _XORG_TRACKER_H_
+#include <stddef.h>
+#include <stdint.h>
#include <errno.h>
#include <drm.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
-#include "exa.h"
+#include <xorg-server.h>
+#include <xf86.h>
+#include "xf86Crtc.h"
+#include <exa.h>
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+#include <damage.h>
+#endif
#include "pipe/p_screen.h"
#include "state_tracker/drm_api.h"
@@ -72,16 +81,23 @@ typedef struct _modesettingRec
unsigned int SaveGeneration;
+ void (*blockHandler)(int, pointer, pointer, pointer);
CreateScreenResourcesProcPtr createScreenResources;
/* gallium */
+ struct drm_api *api;
struct pipe_screen *screen;
struct pipe_context *ctx;
+ boolean d_depth_bits_last;
+ boolean ds_depth_bits_last;
/* exa */
void *exa;
Bool noEvict;
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ DamagePtr damage;
+#endif
} modesettingRec, *modesettingPtr;
#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
@@ -94,7 +110,13 @@ struct pipe_texture *
xorg_exa_get_texture(PixmapPtr pPixmap);
unsigned
-xorg_exa_get_pixmap_handle(PixmapPtr pPixmap);
+xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride);
+
+int
+xorg_exa_set_displayed_usage(PixmapPtr pPixmap);
+
+int
+xorg_exa_set_shared_usage(PixmapPtr pPixmap);
void *
xorg_exa_init(ScrnInfoPtr pScrn);
@@ -119,6 +141,9 @@ driCloseScreen(ScreenPtr pScreen);
void
crtc_init(ScrnInfoPtr pScrn);
+void
+crtc_cursor_destroy(xf86CrtcPtr crtc);
+
/***********************************************************************
* xorg_output.c