diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h index a50b6275fbf..cebad623c8e 100644 --- a/src/mesa/drivers/dri/i915/i915_context.h +++ b/src/mesa/drivers/dri/i915/i915_context.h @@ -200,7 +200,13 @@ struct i915_hw_state { */ struct intel_region *draw_region; struct intel_region *depth_region; - struct intel_region *tex_region[I915_TEX_UNITS]; +/* struct intel_region *tex_region[I915_TEX_UNITS]; */ + + /* Regions aren't actually that appropriate here as the memory may + * be from a PBO or FBO. Just use the buffer id. Will have to do + * this for draw and depth for FBO's... + */ + GLuint tex_buffer[I915_TEX_UNITS]; GLuint tex_offset[I915_TEX_UNITS]; diff --git a/src/mesa/drivers/dri/i915/i915_metaops.c b/src/mesa/drivers/dri/i915/i915_metaops.c index 524e6c98703..f1ed371e69f 100644 --- a/src/mesa/drivers/dri/i915/i915_metaops.c +++ b/src/mesa/drivers/dri/i915/i915_metaops.c @@ -304,35 +304,91 @@ static void meta_texture_blend_replace( struct intel_context *intel ) /* Set up an arbitary piece of memory as a rectangular texture * (including the front or back buffer). */ -static void meta_tex_rect_source( struct intel_context *intel, - struct intel_region *region ) +static GLboolean meta_tex_rect_source( struct intel_context *intel, + GLuint buffer, + GLuint offset, + GLuint pitch, + GLuint height, + GLenum format, + GLenum type) { struct i915_context *i915 = i915_context(&intel->ctx); GLuint unit = 0; GLint numLevels = 1; GLuint *state = i915->meta.Tex[0]; GLuint textureFormat; + GLuint cpp; - GLuint pitch = region->pitch * region->cpp; - - /* XXX: color buffers only: + /* A full implementation of this would do the upload through + * glTexImage2d, and get all the conversion operations at that + * point. We are restricted, but still at least have access to the + * fragment program swizzle. */ - if (region->cpp == 2) - textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); - else - textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888); + switch (format) { + case GL_BGRA: + switch (type) { + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_BYTE: + textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888); + cpp = 4; + break; + default: + return GL_FALSE; + } + break; + case GL_RGBA: + switch (type) { + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_BYTE: + textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888); + cpp = 4; + break; + default: + return GL_FALSE; + } + break; + case GL_BGR: + switch (type) { + case GL_UNSIGNED_SHORT_5_6_5_REV: + textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); + cpp = 2; + break; + default: + return GL_FALSE; + } + break; + case GL_RGB: + switch (type) { + case GL_UNSIGNED_SHORT_5_6_5: + textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); + cpp = 2; + break; + default: + return GL_FALSE; + } + break; + + default: + return GL_FALSE; + } - intel_region_release(intel, &i915->meta.tex_region[0]); - intel_region_reference(&i915->meta.tex_region[0], region); - i915->meta.tex_offset[0] = 0; + if ((pitch * cpp) & 3) { + _mesa_printf("%s: texture is not dword pitch\n", __FUNCTION__); + return GL_FALSE; + } - state[I915_TEXREG_MS3] = (((region->height - 1) << MS3_HEIGHT_SHIFT) | - ((region->pitch - 1) << MS3_WIDTH_SHIFT) | +/* intel_region_release(intel, &i915->meta.tex_region[0]); */ +/* intel_region_reference(&i915->meta.tex_region[0], region); */ + i915->meta.tex_buffer[0] = buffer; + i915->meta.tex_offset[0] = offset; + + state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) | + ((pitch - 1) << MS3_WIDTH_SHIFT) | textureFormat | MS3_USE_FENCE_REGS); - state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | + state[I915_TEXREG_MS4] = (((((pitch * cpp) / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK | ((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT)); @@ -348,6 +404,7 @@ static void meta_tex_rect_source( struct intel_context *intel, state[I915_TEXREG_SS4] = 0; i915->meta.emitted &= ~I915_UPLOAD_TEX(0); + return GL_TRUE; } /* Select between front and back draw buffers. @@ -437,7 +494,7 @@ static void leave_meta_state( struct intel_context *intel ) struct i915_context *i915 = i915_context(&intel->ctx); intel_region_release(intel, &i915->meta.draw_region); intel_region_release(intel, &i915->meta.depth_region); - intel_region_release(intel, &i915->meta.tex_region[0]); +/* intel_region_release(intel, &i915->meta.tex_region[0]); */ SET_STATE(i915, state); } diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c index 3b16d5f4a15..6460f87156f 100644 --- a/src/mesa/drivers/dri/i915/i915_texstate.c +++ b/src/mesa/drivers/dri/i915/i915_texstate.c @@ -123,14 +123,15 @@ static GLboolean i915_update_tex_unit( struct intel_context *intel, memset(state, 0, sizeof(state)); - intel_region_release(intel, &i915->state.tex_region[unit]); +/* intel_region_release(intel, &i915->state.tex_region[unit]); */ if (!intel_finalize_mipmap_tree(intel, unit)) return GL_FALSE; - intel_region_reference(&i915->state.tex_region[unit], - intelObj->mt->region); +/* intel_region_reference(&i915->state.tex_region[unit], */ +/* intelObj->mt->region); */ + i915->state.tex_buffer[unit] = intelObj->mt->region->buffer; i915->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0, intelObj->firstLevel); diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index 3f7f91e530e..014e100bb80 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -289,8 +289,8 @@ static void i915_emit_state( struct intel_context *intel ) for (i = 0 ; i < I915_TEX_UNITS ; i++) if (dirty & I915_UPLOAD_TEX(i)) { - if (state->tex_region[i]) { - OUT_RELOC(state->tex_region[i]->buffer, + if (state->tex_buffer[i]) { + OUT_RELOC(state->tex_buffer[i], BM_MEM_AGP|BM_READ, state->tex_offset[i]); } diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.c b/src/mesa/drivers/dri/i915/intel_batchbuffer.c index ae1dd3997cb..0f7d212d83a 100644 --- a/src/mesa/drivers/dri/i915/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.c @@ -154,6 +154,8 @@ static void do_flush_locked( struct intel_batchbuffer *batch, for (i = 0; i < batch->nr_relocs; i++) { struct buffer_reloc *r = &batch->reloc[i]; + assert(r->elem < batch->list->nr); + DBG("apply fixup at offset 0x%x, elem %d (buf %d, offset 0x%x), delta 0x%x\n", r->offset, r->elem, batch->list->elem[r->elem].buffer, batch->offset[r->elem], r->delta); diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h index 2978ec1ba58..e27d1cccddb 100644 --- a/src/mesa/drivers/dri/i915/intel_context.h +++ b/src/mesa/drivers/dri/i915/intel_context.h @@ -156,9 +156,13 @@ struct intel_context void (*meta_import_pixel_state)( struct intel_context *intel ); - void (*meta_tex_rect_source)( struct intel_context *intel, - struct intel_region *region ); - + GLboolean (*meta_tex_rect_source)( struct intel_context *intel, + GLuint buffer, + GLuint offset, + GLuint pitch, + GLuint height, + GLenum format, + GLenum type); } vtbl; diff --git a/src/mesa/drivers/dri/i915/intel_pixel.c b/src/mesa/drivers/dri/i915/intel_pixel.c index 4bbd5ef5160..5511ddd007d 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel.c +++ b/src/mesa/drivers/dri/i915/intel_pixel.c @@ -39,6 +39,8 @@ GLboolean intel_check_blit_fragment_ops( GLcontext *ctx ) if (ctx->NewState) _mesa_update_state(ctx); + /* Scissor could be done with the blitter: + */ return !(ctx->_ImageTransferState || ctx->Color.AlphaEnabled || ctx->Depth.Test || @@ -50,7 +52,22 @@ GLboolean intel_check_blit_fragment_ops( GLcontext *ctx ) !ctx->Color.ColorMask[2] || !ctx->Color.ColorMask[3] || ctx->Color.ColorLogicOpEnabled || - ctx->Texture._EnabledUnits); + ctx->Texture._EnabledUnits || + ctx->FragmentProgram._Enabled); +} + + +GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx ) +{ + if (ctx->NewState) + _mesa_update_state(ctx); + + /* Some of _ImageTransferState (scale, bias) could be done with + * fragment programs on i915. + */ + return !(ctx->_ImageTransferState || + ctx->Texture._EnabledUnits || + ctx->FragmentProgram._Enabled); } /* The intel_region struct doesn't really do enough to capture the @@ -62,7 +79,8 @@ GLboolean intel_check_blit_format( struct intel_region *region, GLenum format, GLenum type ) { if (region->cpp == 4 && - type == GL_UNSIGNED_INT_8_8_8_8_REV && + (type == GL_UNSIGNED_INT_8_8_8_8_REV || + type == GL_UNSIGNED_BYTE) && format == GL_BGRA ) { return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i915/intel_pixel.h b/src/mesa/drivers/dri/i915/intel_pixel.h index 8f59e4172eb..35699bc3f2d 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel.h +++ b/src/mesa/drivers/dri/i915/intel_pixel.h @@ -34,6 +34,8 @@ void intelInitPixelFuncs( struct dd_function_table *functions ); GLboolean intel_check_blit_fragment_ops( GLcontext *ctx ); +GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx ); + GLboolean intel_check_blit_format( struct intel_region *region, GLenum format, GLenum type ); diff --git a/src/mesa/drivers/dri/i915/intel_pixel_copy.c b/src/mesa/drivers/dri/i915/intel_pixel_copy.c index 763835ceb26..801d75e3712 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel_copy.c +++ b/src/mesa/drivers/dri/i915/intel_pixel_copy.c @@ -78,11 +78,13 @@ static GLboolean do_texture_copypixels( GLcontext *ctx, struct intel_context *intel = intel_context( ctx ); struct intel_region *dst = intel_drawbuf_region( intel ); struct intel_region *src = copypix_src_region(intel, type); + GLenum src_format; + GLenum src_type; if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); - if (!src || !dst) + if (!src || !dst || type != GL_COLOR) return GL_FALSE; intelFlush( &intel->ctx ); @@ -98,10 +100,26 @@ static GLboolean do_texture_copypixels( GLcontext *ctx, */ intel->vtbl.meta_draw_region(intel, dst, intel->depth_region); + if (src->cpp == 2) { + src_format = GL_RGB; + src_type = GL_UNSIGNED_SHORT_5_6_5; + } + else { + src_format = GL_BGRA; + src_type = GL_UNSIGNED_BYTE; + } /* Set the frontbuffer up as a large rectangular texture. */ - intel->vtbl.meta_tex_rect_source( intel, src ); + if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, 0, + src->pitch, + src->height, + src_format, + src_type )) { + intel->vtbl.leave_meta_state(intel); + return GL_FALSE; + } + intel->vtbl.meta_texture_blend_replace( intel ); @@ -258,7 +276,7 @@ void intelCopyPixels( GLcontext *ctx, if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); - if (0 && do_blit_copypixels( ctx, srcx, srcy, width, height, destx, desty, type)) + if (do_blit_copypixels( ctx, srcx, srcy, width, height, destx, desty, type)) return; if (do_texture_copypixels( ctx, srcx, srcy, width, height, destx, desty, type)) diff --git a/src/mesa/drivers/dri/i915/intel_pixel_draw.c b/src/mesa/drivers/dri/i915/intel_pixel_draw.c index 8421f3a9822..43d3f9c9587 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel_draw.c +++ b/src/mesa/drivers/dri/i915/intel_pixel_draw.c @@ -41,72 +41,137 @@ #include "intel_regions.h" #include "intel_pixel.h" #include "intel_buffer_objects.h" +#include "intel_tris.h" #include "bufmgr.h" -static GLboolean do_texture_draw_pixels( struct intel_context *intel, - GLint x, GLint y, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const struct gl_pixelstore_attrib *unpack, - const GLvoid *pixels ) +static GLboolean do_texture_drawpixels( GLcontext *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) { -#if 0 - GLint pitch = unpack->RowLength ? unpack->RowLength : width; - __DRIdrawablePrivate *dPriv = intel->driDrawable; - int textureFormat; - GLenum glTextureFormat; + struct intel_context *intel = intel_context( ctx ); + struct intel_region *dst = intel_drawbuf_region( intel ); + struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj); + GLuint rowLength = unpack->RowLength ? unpack->RowLength : width; + GLuint src_offset; if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); + intelFlush( &intel->ctx ); - if ( ctx->_ImageTransferState || - unpack->SwapBytes || - unpack->LsbFirst || - ctx->Texture._EnabledUnits || - ctx->FragmentProgram._Enabled) { - fprintf(stderr, "%s: cannot use texture path\n", __FUNCTION__); + if (!dst) + return GL_FALSE; + + if (src) { + if (!_mesa_validate_pbo_access(2, unpack, width, height, 1, + format, type, pixels)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels"); + _mesa_printf("%s - _mesa_validate_pbo_access\n", __FUNCTION__); + return GL_TRUE; + } + } + else { + /* PBO only for now: + */ +/* _mesa_printf("%s - not PBO\n", __FUNCTION__); */ return GL_FALSE; } - - glGenTextures(); - glTextureImage2D(); - glBindTexture(); - glEnable(GL_TEXTURE_RECTANGLE_NV); - - glDisable(GL_POLYGON_STIPPLE); - glDisable(GL_CULL); - _mesa_install_vp_passthrough(ctx); - _mesa_push_current(ctx); - - if (intel->Fallback) - goto Fail; + /* There are a couple of things we can't do yet, one of which is + * set the correct state for pixel operations when GL texturing is + * enabled. That's a pretty rare state and probably not worth the + * effort. A completely device-independent version of this may do + * more. + * + * Similarly, we make no attempt to merge metaops processing with + * an enabled fragment program, though it would certainly be + * possible. + */ + if (!intel_check_meta_tex_fragment_ops(ctx)) { + _mesa_printf("%s - bad GL fragment state for metaops texture\n", __FUNCTION__); + return GL_FALSE; + } - glBegin(GL_QUADS); - glVertex3f(); - glTexCoord2f(); - glVertex3f(); - glTexCoord2f(); - glVertex3f(); - glTexCoord2f(); - glVertex3f(); - glTexCoord2f(); - glEnd(); - glFinish(); - - ASSIGN_4V(ctx->Current.Atrrib[VERT_ATTRIB_TEX0], tex0); - - fail: - glDisable(GL_TEXTURE_RECTANGLE_NV); - glDeleteTextures(); - glBindTexture(old); + intel->vtbl.install_meta_state(intel); -#endif - return GL_FALSE; + /* Is this true? Also will need to turn depth testing on according + * to state: + */ + intel->vtbl.meta_no_depth_stencil_write(intel); + + /* Set the 3d engine to draw into the destination region: + */ + intel->vtbl.meta_draw_region(intel, dst, intel->depth_region); + + src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height, + format, type, 0, 0, 0); + + + /* Setup the pbo up as a rectangular texture, if possible. + * + * TODO: This is almost always possible if the i915 fragment + * program is adjusted to correctly swizzle the sampled colors. + * The major exception is any 24bit texture, like RGB888, for which + * there is no hardware support. + */ + if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, src_offset, + rowLength, height, + format, type )) { + intel->vtbl.leave_meta_state(intel); + return GL_FALSE; + } + + intel->vtbl.meta_texture_blend_replace( intel ); + + + LOCK_HARDWARE( intel ); + + { + __DRIdrawablePrivate *dPriv = intel->driDrawable; + GLint srcx, srcy; + GLint dstx, dsty; + + dstx = x; + dsty = dPriv->h - (y + height); + + srcx = 0; /* skiprows/pixels already done */ + srcy = 0; + + { + GLint orig_x = dstx; + GLint orig_y = dsty; + + if (!intel_clip_to_region(ctx, dst, &dstx, &dsty, &width, &height)) + goto out; + + srcx += dstx - orig_x; + srcy += dsty - orig_y; + } + + + /* Just use the regular cliprect mechanism... Does this need to + * even hold the lock??? + */ + intel_meta_draw_quad(intel, + dstx, dstx+width, + dsty, dsty+height, + 0, /* XXX: what z value? */ + 0x00ff00ff, + srcx, srcx+width, + srcy+height, srcy, + INTEL_BATCH_CLIPRECTS); + } + + out: + intel->vtbl.leave_meta_state(intel); + UNLOCK_HARDWARE( intel ); + return GL_TRUE; } @@ -128,14 +193,14 @@ static GLboolean do_texture_draw_pixels( struct intel_context *intel, * data to agp space before performing the blit. (Though it may turn * out to be better/simpler just to use the texture engine). */ -static GLboolean do_blit_draw_pixels( struct intel_context *intel, +static GLboolean do_blit_drawpixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { - GLcontext *ctx = &intel->ctx; + struct intel_context *intel = intel_context(ctx); struct intel_region *dest = intel_drawbuf_region(intel); struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj); GLuint src_offset; @@ -146,8 +211,10 @@ static GLboolean do_blit_draw_pixels( struct intel_context *intel, _mesa_printf("%s\n", __FUNCTION__); - if (!dest) + if (!dest) { + _mesa_printf("%s - no dest\n", __FUNCTION__); return GL_FALSE; + } if (src) { /* This validation should be done by core mesa: @@ -163,7 +230,7 @@ static GLboolean do_blit_draw_pixels( struct intel_context *intel, else { /* PBO only for now: */ -/* _mesa_printf("%s - not PBO\n", __FUNCTION__); */ + _mesa_printf("%s - not PBO\n", __FUNCTION__); return GL_FALSE; } @@ -172,8 +239,8 @@ static GLboolean do_blit_draw_pixels( struct intel_context *intel, return GL_FALSE; } - if (!intel_check_blit_fragment_ops(ctx)) { - _mesa_printf("%s - bad GL fragment state for blit\n", __FUNCTION__); + if (!intel_check_meta_tex_fragment_ops(ctx)) { + _mesa_printf("%s - bad GL fragment state for meta tex\n", __FUNCTION__); return GL_FALSE; } @@ -189,6 +256,7 @@ static GLboolean do_blit_draw_pixels( struct intel_context *intel, rowLength = width; if (ctx->Pixel.ZoomY == -1.0F) { + _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__); return GL_FALSE; /* later */ y -= height; } @@ -259,18 +327,16 @@ void intelDrawPixels( GLcontext *ctx, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { - struct intel_context *intel = intel_context(ctx); - - if (do_texture_draw_pixels( intel, x, y, width, height, format, type, - unpack, pixels )) - return; - - if (do_blit_draw_pixels( intel, x, y, width, height, format, type, + if (do_blit_drawpixels( ctx, x, y, width, height, format, type, unpack, pixels )) return; - if (INTEL_DEBUG & DEBUG_PIXEL) - _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); + if (do_texture_drawpixels( ctx, x, y, width, height, format, type, + unpack, pixels )) + return; + + + _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); _swrast_DrawPixels( ctx, x, y, width, height, format, type, unpack, pixels );