diff options
Diffstat (limited to 'src/gallium/state_trackers/xorg')
| -rw-r--r-- | src/gallium/state_trackers/xorg/Makefile | 37 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/SConscript | 27 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_composite.c | 584 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_composite.h | 25 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_crtc.c | 63 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_dri2.c | 328 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_driver.c | 151 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_exa.c | 470 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_exa.h | 50 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_exa_tgsi.c | 489 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_exa_tgsi.h | 43 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_tracker.h | 29 | ||||
| -rw-r--r-- | src/gallium/state_trackers/xorg/xorg_winsys.h | 2 | 
13 files changed, 1960 insertions, 338 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..c708ac3170 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -0,0 +1,584 @@ +#include "xorg_composite.h" + +#include "xorg_exa_tgsi.h" + +#include "cso_cache/cso_context.h" +#include "util/u_draw_quad.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 }, +}; + +static INLINE void +pixel_to_float4(PictFormatPtr format, +                CARD32 pixel, float *color) +{ +   CARD32	    r, g, b, a; + +   debug_assert(format->type == PictTypeDirect); + +   r = (pixel >> format->direct.red) & format->direct.redMask; +   g = (pixel >> format->direct.green) & format->direct.greenMask; +   b = (pixel >> format->direct.blue) & format->direct.blueMask; +   a = (pixel >> format->direct.alpha) & format->direct.alphaMask; +   color[0] = ((float)r) / ((float)format->direct.redMask); +   color[1] = ((float)g) / ((float)format->direct.greenMask); +   color[2] = ((float)b) / ((float)format->direct.blueMask); +   color[3] = ((float)a) / ((float)format->direct.alphaMask); +} + +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 INLINE int +render_repeat_to_gallium(int mode) +{ +   switch(mode) { +   case RepeatNone: +      return PIPE_TEX_WRAP_CLAMP; +   case RepeatNormal: +      return PIPE_TEX_WRAP_REPEAT; +   case RepeatReflect: +      return PIPE_TEX_WRAP_MIRROR_REPEAT; +   case RepeatPad: +      return PIPE_TEX_WRAP_CLAMP_TO_EDGE; +   default: +      debug_printf("Unsupported repeat mode\n"); +   } +   return PIPE_TEX_WRAP_REPEAT; +} + + +static INLINE void +setup_vertex0(float vertex[2][4], float x, float y, +              float color[4]) +{ +   vertex[0][0] = x; +   vertex[0][1] = y; +   vertex[0][2] = 0.f; /*z*/ +   vertex[0][3] = 1.f; /*w*/ + +   vertex[1][0] = color[0]; /*r*/ +   vertex[1][1] = color[1]; /*g*/ +   vertex[1][2] = color[2]; /*b*/ +   vertex[1][3] = color[3]; /*a*/ +} + +static struct pipe_buffer * +setup_vertex_data0(struct exa_context *ctx, +                   int srcX, int srcY, int maskX, int maskY, +                   int dstX, int dstY, int width, int height) +{ +   float vertices[4][2][4]; + +   /* 1st vertex */ +   setup_vertex0(vertices[0], dstX, dstY, +                 ctx->solid_color); +   /* 2nd vertex */ +   setup_vertex0(vertices[1], dstX + width, dstY, +                 ctx->solid_color); +   /* 3rd vertex */ +   setup_vertex0(vertices[2], dstX + width, dstY + height, +                 ctx->solid_color); +   /* 4th vertex */ +   setup_vertex0(vertices[3], dstX, dstY + height, +                 ctx->solid_color); + +   return pipe_user_buffer_create(ctx->ctx->screen, +                                  vertices, +                                  sizeof(vertices)); +} + +static INLINE void +setup_vertex1(float vertex[2][4], float x, float y, float s, float t) +{ +   vertex[0][0] = x; +   vertex[0][1] = y; +   vertex[0][2] = 0.f; /*z*/ +   vertex[0][3] = 1.f; /*w*/ + +   vertex[1][0] = s;   /*s*/ +   vertex[1][1] = t;   /*t*/ +   vertex[1][2] = 0.f; /*r*/ +   vertex[1][3] = 1.f; /*q*/ +} + +static struct pipe_buffer * +setup_vertex_data1(struct exa_context *ctx, +                   int srcX, int srcY, int maskX, int maskY, +                   int dstX, int dstY, int width, int height) +{ +   float vertices[4][2][4]; +   float s0, t0, s1, t1; +   struct pipe_texture *src = ctx->bound_textures[0]; + +   s0 = srcX / src->width[0]; +   s1 = srcX + width / src->width[0]; +   t0 = srcY / src->height[0]; +   t1 = srcY + height / src->height[0]; + +   /* 1st vertex */ +   setup_vertex1(vertices[0], dstX, dstY, +                 s0, t0); +   /* 2nd vertex */ +   setup_vertex1(vertices[1], dstX + width, dstY, +                 s1, t0); +   /* 3rd vertex */ +   setup_vertex1(vertices[2], dstX + width, dstY + height, +                 s1, t1); +   /* 4th vertex */ +   setup_vertex1(vertices[3], dstX, dstY + height, +                 s0, t1); + +   return pipe_user_buffer_create(ctx->ctx->screen, +                                  vertices, +                                  sizeof(vertices)); +} + + +static INLINE void +setup_vertex2(float vertex[3][4], float x, float y, +              float s0, float t0, float s1, float t1) +{ +   vertex[0][0] = x; +   vertex[0][1] = y; +   vertex[0][2] = 0.f; /*z*/ +   vertex[0][3] = 1.f; /*w*/ + +   vertex[1][0] = s0;  /*s*/ +   vertex[1][1] = t0;  /*t*/ +   vertex[1][2] = 0.f; /*r*/ +   vertex[1][3] = 1.f; /*q*/ + +   vertex[2][0] = s1;  /*s*/ +   vertex[2][1] = t1;  /*t*/ +   vertex[2][2] = 0.f; /*r*/ +   vertex[2][3] = 1.f; /*q*/ +} + +static struct pipe_buffer * +setup_vertex_data2(struct exa_context *ctx, +                   int srcX, int srcY, int maskX, int maskY, +                   int dstX, int dstY, int width, int height) +{ +   float vertices[4][3][4]; +   float st0[4], st1[4]; +   struct pipe_texture *src = ctx->bound_textures[0]; +   struct pipe_texture *mask = ctx->bound_textures[0]; + +   st0[0] = srcX / src->width[0]; +   st0[1] = srcY / src->height[0]; +   st0[2] = srcX + width / src->width[0]; +   st0[3] = srcY + height / src->height[0]; + +   st1[0] = maskX / mask->width[0]; +   st1[1] = maskY / mask->height[0]; +   st1[2] = maskX + width / mask->width[0]; +   st1[3] = maskY + height / mask->height[0]; + +   /* 1st vertex */ +   setup_vertex2(vertices[0], dstX, dstY, +                 st0[0], st0[1], st1[0], st1[1]); +   /* 2nd vertex */ +   setup_vertex2(vertices[1], dstX + width, dstY, +                 st0[2], st0[1], st1[2], st1[1]); +   /* 3rd vertex */ +   setup_vertex2(vertices[2], dstX + width, dstY + height, +                 st0[2], st0[3], st1[2], st1[3]); +   /* 4th vertex */ +   setup_vertex2(vertices[3], dstX, dstY + height, +                 st0[0], st0[3], st1[0], st1[3]); + +   return pipe_user_buffer_create(ctx->ctx->screen, +                                  vertices, +                                  sizeof(vertices)); +} + +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) +{ +   int width = pDstPicture->pDrawable->width; +   int height = pDstPicture->pDrawable->height; + +   set_viewport(exa, width, height, Y0_TOP); +} + +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) { +      if (pSrcPicture->pSourcePict) { +         if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) { +            fs_traits |= FS_SOLID_FILL; +            vs_traits |= VS_SOLID_FILL; +            pixel_to_float4(pSrcPicture->pFormat, +                            pSrcPicture->pSourcePict->solidFill.color, +                            exa->solid_color); +         } else { +            debug_assert("!gradients not supported"); +         } +      } else { +         fs_traits |= FS_COMPOSITE; +         vs_traits |= VS_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_sampler_state src_sampler, mask_sampler; + +   exa->num_bound_samplers = 0; + +   memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); +   memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); + +   if (pSrcPicture && pSrc) { +      unsigned src_wrap = render_repeat_to_gallium( +         pSrcPicture->repeatType); +      src_sampler.wrap_s = src_wrap; +      src_sampler.wrap_t = src_wrap; +      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; +      exa->bound_textures[0] = pSrc->tex; +      ++exa->num_bound_samplers; +   } + +   if (pMaskPicture && pMask) { +      unsigned mask_wrap = render_repeat_to_gallium( +         pMaskPicture->repeatType); +      mask_sampler.wrap_s = mask_wrap; +      mask_sampler.wrap_t = mask_wrap; +      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; +      exa->bound_textures[1] = pMask->tex; +      ++exa->num_bound_samplers; +   } + +   cso_set_samplers(exa->cso, exa->num_bound_samplers, +                    (const struct pipe_sampler_state **)samplers); +   cso_set_sampler_textures(exa->cso, exa->num_bound_samplers, +                            exa->bound_textures); +} + +static void +setup_vs_constant_buffer(struct exa_context *exa, +                         int width, int height) +{ +   const int param_bytes = 8 * sizeof(float); +   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; + +   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 +setup_fs_constant_buffer(struct exa_context *exa) +{ +   const int param_bytes = 4 * sizeof(float); +   float fs_consts[8] = { +      0, 0, 0, 1, +   }; +   struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer; + +   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, fs_consts); +   } +   exa->ctx->set_constant_buffer(exa->ctx, PIPE_SHADER_FRAGMENT, 0, cbuf); +} + +static void +setup_constant_buffers(struct exa_context *exa, PicturePtr pDstPicture) +{ +   int width = pDstPicture->pDrawable->width; +   int height = pDstPicture->pDrawable->height; + +   setup_vs_constant_buffer(exa, width, height); +   setup_fs_constant_buffer(exa); +} + +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); + +   setup_constant_buffers(exa, pDstPicture); + +   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) +{ +   struct pipe_context *pipe = exa->ctx; +   struct pipe_buffer *buf = 0; + +   if (exa->num_bound_samplers == 0 ) { /* solid fill */ +      buf = setup_vertex_data0(exa, +                               srcX, srcY, maskX, maskY, +                               dstX, dstY, width, height); +   } else if (exa->num_bound_samplers == 1 ) /* src */ +      buf = setup_vertex_data1(exa, +                               srcX, srcY, maskX, maskY, +                               dstX, dstY, width, height); +   else if (exa->num_bound_samplers == 2) /* src + mask */ +      buf = setup_vertex_data2(exa, +                               srcX, srcY, maskX, maskY, +                               dstX, dstY, width, height); +   else if (exa->num_bound_samplers == 3) { /* src + mask + dst */ +      debug_assert(!"src/mask/dst not handled right now"); +#if 0 +      buf = setup_vertex_data2(exa, +                               srcX, srcY, maskX, maskY, +                               dstX, dstY, width, height); +#endif +   } + +   if (buf) { +      util_draw_vertex_buffer(pipe, buf, 0, +                              PIPE_PRIM_TRIANGLE_FAN, +                              4,  /* verts */ +                              1 + exa->num_bound_samplers); /* attribs/vert */ + +      pipe_buffer_reference(&buf, NULL); +   } +} + 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; +    struct pipe_transfer *transfer; -    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); -    } +    if (!crtcp->cursor_tex) { +	struct pipe_texture templat; +	unsigned pitch; -    ptr = pipe_buffer_map(ms->screen, crtcp->cursor_buf, PIPE_BUFFER_USAGE_CPU_WRITE); +	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); -    if (ptr) -	memcpy(ptr, image, 64 * 64 * 4); +	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); +    } -    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..6431a0fe25 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -33,97 +33,193 @@  #include "xf86_OSproc.h"  #include "xorg_tracker.h" +#include "xorg_exa.h"  #include "dri2.h"  #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 -driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count) +static Bool +driDoCreateBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int format)  { -    struct pipe_texture *depth, *tex; -    struct pipe_buffer *buf; +    struct pipe_texture *tex = NULL;      ScreenPtr pScreen = pDraw->pScreen;      ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];      modesettingPtr ms = modesettingPTR(pScrn); -    BufferPrivatePtr privates; -    DRI2BufferPtr buffers; +    struct exa_pixmap_priv *exa_priv; +    BufferPrivatePtr private = buffer->driverPrivate;      PixmapPtr pPixmap;      unsigned stride, handle; -    int i; - -    buffers = xcalloc(count, sizeof *buffers); -    if (!buffers) -	goto fail_buffers; -    privates = xcalloc(count, sizeof *privates); -    if (!privates) -	goto fail_privates; +    if (pDraw->type == DRAWABLE_PIXMAP) +	pPixmap = (PixmapPtr) pDraw; +    else +	pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw); +    exa_priv = exaGetPixmapDriverPrivate(pPixmap); -    depth = NULL; -    for (i = 0; i < count; i++) { -	pPixmap = NULL; -	tex = NULL; -	buf = NULL; -	if (attachments[i] == DRI2BufferFrontLeft) { -	    if (pDraw->type == DRAWABLE_PIXMAP) -		pPixmap = (PixmapPtr) pDraw; -	    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; -	    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); -	} else { +    switch (buffer->attachment) { +    default: +	if (buffer->attachment != DRI2BufferFakeFrontLeft || +	    pDraw->type != DRAWABLE_PIXMAP) { +	    private->pPixmap = (*pScreen->CreatePixmap)(pScreen, pDraw->width, +							pDraw->height, +							pDraw->depth, +							0); +	} +	break; +    case DRI2BufferFrontLeft: +	break; +    case DRI2BufferStencil: +#if defined(DRI2INFOREC_VERSION) && DRI2INFOREC_VERSION > 2 +    case DRI2BufferDepthStencil: +	if (exa_priv->depth_stencil_tex && +	    !pf_is_depth_stencil(exa_priv->depth_stencil_tex->format)) +	    exa_priv->depth_stencil_tex = NULL; +        /* Fall through */ +#endif +    case DRI2BufferDepth: +	if (exa_priv->depth_stencil_tex) +	    pipe_texture_reference(&tex, exa_priv->depth_stencil_tex); +        else {  	    struct pipe_texture template;  	    memset(&template, 0, sizeof(template));  	    template.target = PIPE_TEXTURE_2D; -	    template.format = PIPE_FORMAT_A8R8G8B8_UNORM; +	    if (buffer->attachment == DRI2BufferDepth) +		template.format = ms->ds_depth_bits_last ? +		    PIPE_FORMAT_X8Z24_UNORM : PIPE_FORMAT_Z24X8_UNORM; +	    else +		template.format = ms->ds_depth_bits_last ? +		    PIPE_FORMAT_S8Z24_UNORM : PIPE_FORMAT_Z24S8_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); +	    pipe_texture_reference(&exa_priv->depth_stencil_tex, tex);  	} +	break; +    } + +    if (!private->pPixmap) { +	private->pPixmap = pPixmap; +	pPixmap->refcnt++; +    } + +    if (!tex) { +	xorg_exa_set_shared_usage(private->pPixmap); +	pScreen->ModifyPixmapHeader(private->pPixmap, 0, 0, 0, 0, 0, NULL); +	tex = xorg_exa_get_texture(private->pPixmap); +    } + +    if (!tex) +	FatalError("NO TEXTURE IN DRI2\n"); + +    ms->api->shared_handle_from_texture(ms->api, ms->screen, tex, &stride, &handle); + +    buffer->name = handle; +    buffer->pitch = stride; +    buffer->cpp = 4; +    buffer->driverPrivate = private; +    buffer->flags = 0; /* not tiled */ +    private->tex = tex; + +    return TRUE; +} + +static void +driDoDestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer) +{ +    ScreenPtr pScreen = pDraw->pScreen; +    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; +    modesettingPtr ms = modesettingPTR(pScrn); +    BufferPrivatePtr private = buffer->driverPrivate; +    struct exa_pixmap_priv *exa_priv = exaGetPixmapDriverPrivate(private->pPixmap); + +    pipe_texture_reference(&private->tex, NULL); +    ms->screen->fence_reference(ms->screen, &private->fence, NULL); +    pipe_texture_reference(&exa_priv->depth_stencil_tex, NULL); +    (*pScreen->DestroyPixmap)(private->pPixmap); +} + +#if defined(DRI2INFOREC_VERSION) && DRI2INFOREC_VERSION > 2 + +static DRI2BufferPtr +driCreateBuffer(DrawablePtr pDraw, unsigned int attachment, unsigned int format) +{ +    DRI2BufferPtr buffer; +    BufferPrivatePtr private; + +    buffer = xcalloc(1, sizeof *buffer); +    if (!buffer) +	return NULL; + +    private = xcalloc(1, sizeof *private); +    if (!private) { +	goto fail; +    } + +    buffer->attachment = attachment; +    buffer->driverPrivate = private; + +    if (driDoCreateBuffer(pDraw, buffer, format)) +	return buffer; + +    xfree(private); +fail: +    xfree(buffer); +    return NULL; +} + +static void +driDestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer) +{ +    driDoDestroyBuffer(pDraw, buffer); + +    xfree(buffer->driverPrivate); +    xfree(buffer); +} -	drm_api_hooks.buffer_from_texture(tex, &buf, &stride); -	drm_api_hooks.global_handle_from_buffer(ms->screen, buf, &handle); +#else /* DRI2INFOREC_VERSION <= 2 */ -	buffers[i].name = handle; +static DRI2BufferPtr +driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count) +{ +    BufferPrivatePtr privates; +    DRI2BufferPtr buffers; +    int i; + +    buffers = xcalloc(count, sizeof *buffers); +    if (!buffers) +	goto fail_buffers; + +    privates = xcalloc(count, sizeof *privates); +    if (!privates) +	goto fail_privates; + +    for (i = 0; i < count; i++) {  	buffers[i].attachment = attachments[i]; -	buffers[i].pitch = stride; -	buffers[i].cpp = 4;  	buffers[i].driverPrivate = &privates[i]; -	buffers[i].flags = 0; /* not tiled */ -	privates[i].pPixmap = pPixmap; -	privates[i].buf = buf; -	privates[i].tex = tex; + +	if (!driDoCreateBuffer(pDraw, &buffers[i], 0)) +	    goto fail;      }      return buffers; +fail: +    xfree(privates);  fail_privates:      xfree(buffers);  fail_buffers: @@ -133,20 +229,10 @@ fail_buffers:  static void  driDestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count)  { -    ScreenPtr pScreen = pDraw->pScreen; -    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -    modesettingPtr ms = modesettingPTR(pScrn); -    BufferPrivatePtr private;      int i;      for (i = 0; i < count; i++) { -	private = buffers[i].driverPrivate; - -	if (private->pPixmap) -	    (*pScreen->DestroyPixmap)(private->pPixmap); - -	pipe_texture_reference(&private->tex, NULL); -	pipe_buffer_reference(&private->buf, NULL); +	driDoDestroyBuffer(pDraw, &buffers[i]);      }      if (buffers) { @@ -155,6 +241,8 @@ driDestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count)      }  } +#endif /* DRI2INFOREC_VERSION */ +  static void  driCopyRegion(DrawablePtr pDraw, RegionPtr pRegion,                DRI2BufferPtr pDestBuffer, DRI2BufferPtr pSrcBuffer) @@ -164,19 +252,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"); +	} +    } -    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); +    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); -    ms->ctx->surface_copy(ms->ctx, dst_surf, 0, 0, src_surf, -			  0, 0, pDraw->width, pDraw->height); +    /* 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); -    pipe_surface_reference(&dst_surf, NULL); -    pipe_surface_reference(&src_surf, NULL); +	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); + +    FreeScratchGC(gc); + +    ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS, +		   pDestBuffer->attachment == DRI2BufferFrontLeft ? +		   &dst_priv->fence : NULL);  }  Bool @@ -186,18 +338,34 @@ driScreenInit(ScreenPtr pScreen)      modesettingPtr ms = modesettingPTR(pScrn);      DRI2InfoRec dri2info; -    dri2info.version = 1; -    dri2info.fd = ms->fd; -#if 0 -    dri2info.driverName = pScrn->name; +#if defined(DRI2INFOREC_VERSION) +    dri2info.version = DRI2INFOREC_VERSION;  #else -    dri2info.driverName = "i915"; /* FIXME */ +    dri2info.version = 1;  #endif +    dri2info.fd = ms->fd; + +    dri2info.driverName = pScrn->driverName;      dri2info.deviceName = "/dev/dri/card0"; /* FIXME */ +#if defined(DRI2INFOREC_VERSION) && DRI2INFOREC_VERSION > 2 +    dri2info.CreateBuffer = driCreateBuffer; +    dri2info.DestroyBuffer = driDestroyBuffer; +#else      dri2info.CreateBuffers = driCreateBuffers;      dri2info.DestroyBuffers = driDestroyBuffers; +#endif      dri2info.CopyRegion = driCopyRegion; +    dri2info.Wait = NULL; + +    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..643b6b3b9e 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -33,10 +33,8 @@  #include "xf86.h"  #include "xf86_OSproc.h"  #include "compiler.h" -#include "xf86RAC.h"  #include "xf86PciInfo.h"  #include "xf86Pci.h" -#include "xf86Resources.h"  #include "mipointer.h"  #include "micmap.h"  #include <X11/extensions/randr.h> @@ -54,6 +52,7 @@  #include <pciaccess.h> +#include "pipe/p_context.h"  #include "xorg_tracker.h"  #include "xorg_winsys.h" @@ -84,41 +83,9 @@ static const OptionInfoRec Options[] = {  };  /* - * Functions that might be needed - */ - -static const char *exaSymbols[] = { -    "exaGetVersion", -    "exaDriverInit", -    "exaDriverFini", -    "exaOffscreenAlloc", -    "exaOffscreenFree", -    "exaWaitSync", -    NULL -}; - -static const char *fbSymbols[] = { -    "fbPictureInit", -    "fbScreenInit", -    NULL -}; - -static const char *ddcSymbols[] = { -    "xf86PrintEDID", -    "xf86SetDDCproperties", -    NULL -}; - -/*   * Exported Xorg driver functions to winsys   */ -void -xorg_tracker_loader_ref_sym_lists() -{ -    LoaderRefSymLists(exaSymbols, fbSymbols, ddcSymbols, NULL); -} -  const OptionInfoRec *  xorg_tracker_available_options(int chipid, int busid)  { @@ -179,8 +146,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 +157,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; @@ -282,10 +254,6 @@ PreInit(ScrnInfoPtr pScrn, int flags)      } else  	ms->entityPrivate = NULL; -    if (xf86RegisterResources(ms->pEnt->index, NULL, ResNone)) { -	return FALSE; -    } -      if (xf86IsEntityShared(pScrn->entityList[0])) {  	if (xf86IsPrimInitDone(pScrn->entityList[0])) {  	    /* do something */ @@ -300,12 +268,12 @@ 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)  	return FALSE; -    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;      pScrn->monitor = pScrn->confScreen->monitor;      pScrn->progClock = TRUE;      pScrn->rgbBits = 8; @@ -391,8 +359,6 @@ PreInit(ScrnInfoPtr pScrn, int flags)  	return FALSE;      } -    xf86LoaderReqSymLists(fbSymbols, NULL); -      xf86LoadSubModule(pScrn, "exa");  #ifdef DRI2 @@ -418,6 +384,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 +429,7 @@ CreateScreenResources(ScreenPtr pScreen)      modesettingPtr ms = modesettingPTR(pScrn);      PixmapPtr rootPixmap;      Bool ret; +    unsigned handle, stride;      ms->noEvict = TRUE; @@ -434,21 +439,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 +501,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 +550,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 +620,6 @@ FreeScreen(int scrnIndex, int flags)      FreeRec(xf86Screens[scrnIndex]);  } -/* HACK */ -void -cursor_destroy(xf86CrtcPtr crtc); -  static void  LeaveVT(int scrnIndex, int flags)  { @@ -608,7 +631,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 +645,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 +661,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 +711,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..a17a71f23a 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 @@ -108,13 +98,75 @@ ExaMarkSync(ScreenPtr pScreen)  }  static Bool +ExaDownloadFromScreen(PixmapPtr pPix, int x,  int y, int w,  int h, char *dst, +		      int dst_pitch) +{ +    ScreenPtr pScreen = pPix->drawable.pScreen; +    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; +    modesettingPtr ms = modesettingPTR(pScrn); +    struct exa_context *exa = ms->exa; +    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); +    struct pipe_transfer *transfer; + +    if (!priv || !priv->tex) +	return FALSE; + +    if (exa->ctx->is_texture_referenced(exa->ctx, priv->tex, 0, 0) & +	PIPE_REFERENCED_FOR_WRITE) +	exa->ctx->flush(exa->ctx, 0, NULL); + +    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, +					   PIPE_TRANSFER_READ, x, y, w, h); +    if (!transfer) +	return FALSE; + +    util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0, +		   w, h, exa->scrn->transfer_map(exa->scrn, transfer), +		   transfer->stride, 0, 0); + +    exa->scrn->transfer_unmap(exa->scrn, transfer); +    exa->scrn->tex_transfer_destroy(transfer); + +    return TRUE; +} + +static Bool +ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, +		  int src_pitch) +{ +    ScreenPtr pScreen = pPix->drawable.pScreen; +    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; +    modesettingPtr ms = modesettingPTR(pScrn); +    struct exa_context *exa = ms->exa; +    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); +    struct pipe_transfer *transfer; + +    if (!priv || !priv->tex) +	return FALSE; + +    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, +					   PIPE_TRANSFER_WRITE, x, y, w, h); +    if (!transfer) +	return FALSE; + +    util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), +		   &priv->tex->block, transfer->stride, 0, 0, w, h, +		   (unsigned char*)src, src_pitch, 0, 0); + +    exa->scrn->transfer_unmap(exa->scrn, transfer); +    exa->scrn->tex_transfer_destroy(transfer); + +    return TRUE; +} + +static Bool  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 +178,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 +201,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 +216,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 +225,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,11 +247,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; - -    if (1) -        return FALSE; +    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); +    struct exa_context *exa = ms->exa;      if (pPixmap->drawable.depth < 15)  	return FALSE; @@ -221,12 +275,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 +291,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 +313,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 +324,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 +338,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 +367,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 +388,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 +404,7 @@ ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)  static Bool  ExaPixmapIsOffscreen(PixmapPtr pPixmap)  { -    struct PixmapPriv *priv; +    struct exa_pixmap_priv *priv;      priv = exaGetPixmapDriverPrivate(pPixmap); @@ -357,14 +417,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 +471,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,11 +485,11 @@ 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) +    if (!priv || pPixData)  	return FALSE;      if (depth <= 0) @@ -419,35 +511,69 @@ 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)) { -	pipe_texture_reference(&priv->tex, NULL); -    } +    if (!priv->tex || +        (priv->tex->width[0] != width || +         priv->tex->height[0] != height || +         priv->tex_flags != priv->flags)) { +	struct pipe_texture *texture = NULL; -    if (!priv->tex) { -	struct pipe_texture template; +#ifdef DRM_MODE_FEATURE_DIRTYFB +	if (priv->flags) +#endif +	{ +	    struct pipe_texture template; -	memset(&template, 0, sizeof(template)); -	template.target = PIPE_TEXTURE_2D; -	exa_get_pipe_format(depth, &template.format, &bitsPerPixel); -	pf_get_block(template.format, &template.block); -	template.width[0] = width; -	template.height[0] = height; -	template.depth[0] = 1; -	template.last_level = 0; -	template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; -	priv->tex = exa->scrn->texture_create(exa->scrn, &template); -    } +	    memset(&template, 0, sizeof(template)); +	    template.target = PIPE_TEXTURE_2D; +	    exa_get_pipe_format(depth, &template.format, &bitsPerPixel); +	    pf_get_block(template.format, &template.block); +	    template.width[0] = width; +	    template.height[0] = height; +	    template.depth[0] = 1; +	    template.last_level = 0; +	    template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags; +	    priv->tex_flags = priv->flags; +	    texture = exa->scrn->texture_create(exa->scrn, &template); -    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), -                       &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); +	    if (priv->tex) { +		struct pipe_surface *dst_surf; + +		dst_surf = exa->scrn->get_tex_surface(exa->scrn, texture, 0, 0, 0, +						      PIPE_BUFFER_USAGE_GPU_WRITE); +		priv->src_surf = exa_gpu_surface(exa, priv); +		exa->ctx->surface_copy(exa->ctx, dst_surf, 0, 0, priv->src_surf, +				       0, 0, min(width, texture->width[0]), +				       min(height, texture->height[0])); +		exa->scrn->tex_surface_destroy(dst_surf); +		exa->scrn->tex_surface_destroy(priv->src_surf); +		priv->src_surf = NULL; +	    } else if (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, texture, 0, 0, 0, +						PIPE_TRANSFER_WRITE, +						0, 0, width, height); +		util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), +			       &texture->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); +	    } +	} +#ifdef DRM_MODE_FEATURE_DIRTYFB +	else { +	    xfree(pPixmap->devPrivate.ptr); +	    pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height * +					     pPixmap->devKind); +	} +#endif + +	pipe_texture_reference(&priv->tex, texture);      }      return TRUE; @@ -456,87 +582,119 @@ 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->shaders) { +      xorg_shaders_destroy(exa->shaders); +   } + +   if (vsbuf && vsbuf->buffer) +      pipe_buffer_reference(&vsbuf->buffer, NULL); + +   if (fsbuf && fsbuf->buffer) +      pipe_buffer_reference(&fsbuf->buffer, NULL); + +   if (exa->cso) { +      cso_release_all(exa->cso); +      cso_destroy_context(exa->cso); +   } -    if (exa->ctx) -	exa->ctx->destroy(exa->ctx); +   if (exa->ctx) +      exa->ctx->destroy(exa->ctx); -    exaDriverFini(pScrn->pScreen); -    xfree(exa); -    ms->exa = NULL; +   exaDriverFini(pScrn->pScreen); +   xfree(exa); +   ms->exa = NULL;  }  void *  xorg_exa_init(ScrnInfoPtr pScrn)  { -    modesettingPtr ms = modesettingPTR(pScrn); -    struct exa_entity *exa; -    ExaDriverPtr pExa; +   modesettingPtr ms = modesettingPTR(pScrn); +   struct exa_context *exa; +   ExaDriverPtr pExa; -    exa = xcalloc(1, sizeof(struct exa_entity)); -    if (!exa) -	return NULL; +   exa = xcalloc(1, sizeof(struct exa_context)); +   if (!exa) +      return NULL; -    pExa = exaDriverAlloc(); -    if (!pExa) { -	goto out_err; -    } +   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; +   memset(pExa, 0, sizeof(*pExa)); -    if (!exaDriverInit(pScrn->pScreen, pExa)) { -	goto out_err; -    } +   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->DownloadFromScreen = ExaDownloadFromScreen; +   pExa->UploadToScreen     = ExaUploadToScreen; +   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; +   exa->scrn = ms->screen; +   exa->ctx = ms->api->create_context(ms->api, exa->scrn); +   /* Share context with DRI */ +   ms->ctx = exa->ctx; -    return (void *)exa; +   exa->cso = cso_create_context(exa->ctx); +   exa->shaders = xorg_shaders_create(exa); -  out_err: -    xorg_exa_close(pScrn); +   return (void *)exa; + +out_err: +   xorg_exa_close(pScrn); + +   return NULL; +} + +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..5b515be139 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_exa.h @@ -0,0 +1,50 @@ +#ifndef XORG_EXA_H +#define XORG_EXA_H + +#include "xorg_tracker.h" + +#include <pipe/p_state.h> + +struct cso_context; +struct xorg_shaders; + +/* src + mask + dst */ +#define MAX_EXA_SAMPLERS 3 + +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 pipe_texture *bound_textures[MAX_EXA_SAMPLERS]; +   int num_bound_samplers; + +   float solid_color[4]; +}; + + +struct exa_pixmap_priv +{ +   int flags; +   int tex_flags; + +   struct pipe_texture *tex; +   struct pipe_texture *depth_stencil_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..cfee10c3b3 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c @@ -0,0 +1,489 @@ +#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]    = vertex pos + * IN[1]    = src tex coord | solid fill color + * IN[2]    = mask tex coord + * IN[3]    = dst tex coord + * CONST[0] = (2/dst_width, 2/dst_height, 1, 1) + * CONST[1] = (-1, -1, 0, 0) + * + * OUT[0]   = vertex pos + * OUT[1]   = src tex coord | solid fill color + * OUT[2]   = mask tex coord + * OUT[3]   = dst tex coord + */ + +/* Fragment shader: + * SAMP[0]  = src + * SAMP[1]  = mask + * SAMP[2]  = dst + * IN[0]    = pos src | solid fill color + * 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 +linear_gradient(struct ureg_program *ureg, +                struct ureg_dst out, +                struct ureg_src pos, +                struct ureg_src sampler, +                struct ureg_src coords, +                struct ureg_src const0124, +                struct ureg_src matrow0, +                struct ureg_src matrow1, +                struct ureg_src matrow2) +{ +   struct ureg_dst temp0 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp1 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp2 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp3 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp4 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp5 = ureg_DECL_temporary(ureg); + +   ureg_MOV(ureg, +            ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos); +   ureg_MOV(ureg, +            ureg_writemask(temp0, TGSI_WRITEMASK_Z), +            ureg_scalar(const0124, TGSI_SWIZZLE_Y)); + +   ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); +   ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); +   ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); +   ureg_RCP(ureg, temp3, ureg_src(temp3)); +   ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); +   ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); + +   ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_X), +            ureg_src(temp1)); +   ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_Y), +            ureg_src(temp2)); + +   ureg_MUL(ureg, temp0, +            ureg_scalar(coords, TGSI_SWIZZLE_Y), +            ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_Y)); +   ureg_MAD(ureg, temp1, +            ureg_scalar(coords, TGSI_SWIZZLE_X), +            ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_X), +            ureg_src(temp0)); + +   ureg_MUL(ureg, temp2, +            ureg_src(temp1), +            ureg_scalar(coords, TGSI_SWIZZLE_Z)); + +   ureg_TEX(ureg, out, +            TGSI_TEXTURE_1D, ureg_src(temp2), sampler); + +   ureg_release_temporary(ureg, temp0); +   ureg_release_temporary(ureg, temp1); +   ureg_release_temporary(ureg, temp2); +   ureg_release_temporary(ureg, temp3); +   ureg_release_temporary(ureg, temp4); +   ureg_release_temporary(ureg, temp5); +} + + +static void +radial_gradient(struct ureg_program *ureg, +                struct ureg_dst out, +                struct ureg_src pos, +                struct ureg_src sampler, +                struct ureg_src coords, +                struct ureg_src const0124, +                struct ureg_src matrow0, +                struct ureg_src matrow1, +                struct ureg_src matrow2) +{ +   struct ureg_dst temp0 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp1 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp2 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp3 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp4 = ureg_DECL_temporary(ureg); +   struct ureg_dst temp5 = ureg_DECL_temporary(ureg); + +   ureg_MOV(ureg, +            ureg_writemask(temp0, TGSI_WRITEMASK_XY), +            pos); +   ureg_MOV(ureg, +            ureg_writemask(temp0, TGSI_WRITEMASK_Z), +            ureg_scalar(const0124, TGSI_SWIZZLE_Y)); + +   ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); +   ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); +   ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); +   ureg_RCP(ureg, temp3, ureg_src(temp3)); +   ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); +   ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); + +   ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_X), +            ureg_src(temp1)); +   ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_Y), +            ureg_src(temp2)); + +   ureg_MUL(ureg, temp0, ureg_scalar(coords, TGSI_SWIZZLE_Y), +            ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); +   ureg_MAD(ureg, temp1, +            ureg_scalar(coords, TGSI_SWIZZLE_X), +            ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), +            ureg_src(temp0)); +   ureg_ADD(ureg, temp1, +            ureg_src(temp1), ureg_src(temp1)); +   ureg_MUL(ureg, temp3, +            ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y), +            ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); +   ureg_MAD(ureg, temp4, +            ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), +            ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), +            ureg_src(temp3)); +   ureg_MOV(ureg, temp4, ureg_negate(ureg_src(temp4))); +   ureg_MUL(ureg, temp2, +            ureg_scalar(coords, TGSI_SWIZZLE_Z), +            ureg_src(temp4)); +   ureg_MUL(ureg, temp0, +            ureg_scalar(const0124, TGSI_SWIZZLE_W), +            ureg_src(temp2)); +   ureg_MUL(ureg, temp3, +            ureg_src(temp1), ureg_src(temp1)); +   ureg_SUB(ureg, temp2, +            ureg_src(temp3), ureg_src(temp0)); +   ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2))); +   ureg_RCP(ureg, temp2, ureg_src(temp2)); +   ureg_SUB(ureg, temp1, +            ureg_src(temp2), ureg_src(temp1)); +   ureg_ADD(ureg, temp0, +            ureg_scalar(coords, TGSI_SWIZZLE_Z), +            ureg_scalar(coords, TGSI_SWIZZLE_Z)); +   ureg_RCP(ureg, temp0, ureg_src(temp0)); +   ureg_MUL(ureg, temp2, +            ureg_src(temp1), ureg_src(temp0)); +   ureg_TEX(ureg, out, TGSI_TEXTURE_1D, +            ureg_src(temp2), sampler); + +   ureg_release_temporary(ureg, temp0); +   ureg_release_temporary(ureg, temp1); +   ureg_release_temporary(ureg, temp2); +   ureg_release_temporary(ureg, temp3); +   ureg_release_temporary(ureg, temp4); +   ureg_release_temporary(ureg, temp5); +} + +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; +   boolean is_fill = vs_traits & VS_FILL; +   boolean is_composite = vs_traits & VS_COMPOSITE; +   boolean has_mask = vs_traits & VS_MASK; + +   ureg = ureg_create(TGSI_PROCESSOR_VERTEX); +   if (ureg == NULL) +      return 0; + +   const0 = ureg_DECL_constant(ureg); +   const1 = ureg_DECL_constant(ureg); + +   /* it has to be either a fill or a composite op */ +   debug_assert(is_fill ^ is_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 (is_composite) { +      src = ureg_DECL_vs_input(ureg, +                               TGSI_SEMANTIC_GENERIC, 1); +      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); +      ureg_MOV(ureg, dst, src); +   } +   if (is_fill) { +      src = ureg_DECL_vs_input(ureg, +                               TGSI_SEMANTIC_COLOR, 1); +      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1); +      ureg_MOV(ureg, dst, src); +   } + +   if (has_mask) { +      src = ureg_DECL_vs_input(ureg, +                               TGSI_SEMANTIC_GENERIC, 2); +      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2); +      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_input, mask_pos; +   struct ureg_dst src, mask; +   struct ureg_dst out; +   boolean has_mask = fs_traits & FS_MASK; +   boolean is_fill = fs_traits & FS_FILL; +   boolean is_composite = fs_traits & FS_COMPOSITE; +   boolean is_solid   = fs_traits & FS_SOLID_FILL; +   boolean is_lingrad = fs_traits & FS_LINGRAD_FILL; +   boolean is_radgrad = fs_traits & FS_RADGRAD_FILL; + +   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); +   if (ureg == NULL) +      return 0; + +   /* it has to be either a fill or a composite op */ +   debug_assert(is_fill ^ is_composite); + +   out = ureg_DECL_output(ureg, +                          TGSI_SEMANTIC_COLOR, +                          0); + +   if (is_composite) { +      src_sampler = ureg_DECL_sampler(ureg, 0); +      src_input = ureg_DECL_fs_input(ureg, +                                     TGSI_SEMANTIC_POSITION, +                                     0, +                                     TGSI_INTERPOLATE_PERSPECTIVE); +   } +   if (is_fill) { +      if (is_solid) +         src_input = ureg_DECL_fs_input(ureg, +                                        TGSI_SEMANTIC_COLOR, +                                        0, +                                        TGSI_INTERPOLATE_PERSPECTIVE); +      else +         src_input = ureg_DECL_fs_input(ureg, +                                        TGSI_SEMANTIC_POSITION, +                                        0, +                                        TGSI_INTERPOLATE_PERSPECTIVE); +   } + +   if (has_mask) { +      mask_sampler = ureg_DECL_sampler(ureg, 1); +      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, 2); +   dst_pos = ureg_DECL_fs_input(ureg, +                                TGSI_SEMANTIC_POSITION, +                                2, +                                TGSI_INTERPOLATE_PERSPECTIVE); +#endif + +   if (is_composite) { +      if (has_mask) +         src = ureg_DECL_temporary(ureg); +      else +         src = out; +      ureg_TEX(ureg, src, +               TGSI_TEXTURE_2D, src_input, src_sampler); +   } else if (is_fill) { +      if (is_solid) { +         if (has_mask) +            src = ureg_dst(src_input); +         else +            ureg_MOV(ureg, out, src_input); +      } else if (is_lingrad || is_radgrad) { +         struct ureg_src coords, const0124, +            matrow0, matrow1, matrow2; + +         if (has_mask) +            src = ureg_DECL_temporary(ureg); +         else +            src = out; + +         coords = ureg_DECL_constant(ureg); +         const0124 = ureg_DECL_constant(ureg); +         matrow0 = ureg_DECL_constant(ureg); +         matrow1 = ureg_DECL_constant(ureg); +         matrow2 = ureg_DECL_constant(ureg); + +         if (is_lingrad) { +            linear_gradient(ureg, src, +                            src_input, src_sampler, +                            coords, const0124, +                            matrow0, matrow1, matrow2); +         } else if (is_radgrad) { +            radial_gradient(ureg, src, +                            src_input, src_sampler, +                            coords, const0124, +                            matrow0, matrow1, matrow2); +         } +      } else +         debug_assert(!"Unknown fill type!"); +   } + +   if (has_mask) { +      mask = ureg_DECL_temporary(ureg); +      ureg_TEX(ureg, mask, +               TGSI_TEXTURE_2D, mask_pos, mask_sampler); +      /* src IN mask */ +      src_in_mask(ureg, out, ureg_src(src), ureg_src(mask)); +      ureg_release_temporary(ureg, mask); +   } + +   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..1535a0c8c3 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h @@ -0,0 +1,43 @@ +#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_SOLID_FILL       = 1 << 2, +   VS_LINGRAD_FILL     = 1 << 3, +   VS_RADGRAD_FILL     = 1 << 4, +   VS_FILL             = (VS_SOLID_FILL | +                          VS_LINGRAD_FILL | +                          VS_RADGRAD_FILL) +   /*VS_TRANSFORM      = 1 << 5*/ +}; + +enum xorg_fs_traits { +   FS_COMPOSITE        = 1 << 0, +   FS_MASK             = 1 << 1, +   FS_SOLID_FILL       = 1 << 2, +   FS_LINGRAD_FILL     = 1 << 3, +   FS_RADGRAD_FILL     = 1 << 4, +   FS_FILL             = (FS_SOLID_FILL | +                          FS_LINGRAD_FILL | +                          FS_RADGRAD_FILL) +}; + +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 diff --git a/src/gallium/state_trackers/xorg/xorg_winsys.h b/src/gallium/state_trackers/xorg/xorg_winsys.h index d523080e90..47ee4b9ffd 100644 --- a/src/gallium/state_trackers/xorg/xorg_winsys.h +++ b/src/gallium/state_trackers/xorg/xorg_winsys.h @@ -37,7 +37,6 @@  #include "xorg-server.h"  #include "xf86.h" -#include "xf86Resources.h"  #include "pciaccess.h"  #ifndef XSERVER_LIBPCIACCESS @@ -46,6 +45,5 @@  void xorg_tracker_set_functions(ScrnInfoPtr scrn);  const OptionInfoRec * xorg_tracker_available_options(int chipid, int busid); -void xorg_tracker_loader_ref_sym_lists(void);  #endif  | 
