state/relocations. - Implement basic texture engine drawpixels.tags/texman_0_1_20060325
| @@ -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]; | |||
| @@ -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; | |||
| } | |||
| /* 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] = (((region->height - 1) << MS3_HEIGHT_SHIFT) | | |||
| ((region->pitch - 1) << MS3_WIDTH_SHIFT) | | |||
| 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); | |||
| } | |||
| @@ -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); | |||
| @@ -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]); | |||
| } | |||
| @@ -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); | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| @@ -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 ); | |||
| @@ -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)) | |||
| @@ -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; | |||
| glBegin(GL_QUADS); | |||
| glVertex3f(); | |||
| glTexCoord2f(); | |||
| glVertex3f(); | |||
| glTexCoord2f(); | |||
| glVertex3f(); | |||
| glTexCoord2f(); | |||
| glVertex3f(); | |||
| glTexCoord2f(); | |||
| glEnd(); | |||
| glFinish(); | |||
| ASSIGN_4V(ctx->Current.Atrrib[VERT_ATTRIB_TEX0], tex0); | |||
| /* 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; | |||
| } | |||
| intel->vtbl.install_meta_state(intel); | |||
| /* 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); | |||
| fail: | |||
| glDisable(GL_TEXTURE_RECTANGLE_NV); | |||
| glDeleteTextures(); | |||
| glBindTexture(old); | |||
| /* 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; | |||
| } | |||
| #endif | |||
| return GL_FALSE; | |||
| /* 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_blit_drawpixels( ctx, x, y, width, height, format, type, | |||
| unpack, pixels )) | |||
| return; | |||
| if (do_texture_draw_pixels( intel, x, y, width, height, format, type, | |||
| if (do_texture_drawpixels( ctx, x, y, width, height, format, type, | |||
| unpack, pixels )) | |||
| return; | |||
| if (do_blit_draw_pixels( intel, x, y, width, height, format, type, | |||
| unpack, pixels )) | |||
| return; | |||
| if (INTEL_DEBUG & DEBUG_PIXEL) | |||
| _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); | |||
| _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); | |||
| _swrast_DrawPixels( ctx, x, y, width, height, format, type, | |||
| unpack, pixels ); | |||