summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/i915/i830_metaops.c
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2004-06-10 12:48:07 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2004-06-10 12:48:07 +0000
commit41b58954e1742493452b91d9ecdb761db5de3bed (patch)
treef170cda67626d1a0d4e7e51ea502553b0f144077 /src/mesa/drivers/dri/i915/i830_metaops.c
parentd7f76c7c8830882d849b42777ca601859ffac15a (diff)
New driver for i915 as well as older i830/i845/i865 chipsets.
Diffstat (limited to 'src/mesa/drivers/dri/i915/i830_metaops.c')
-rw-r--r--src/mesa/drivers/dri/i915/i830_metaops.c699
1 files changed, 699 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i915/i830_metaops.c b/src/mesa/drivers/dri/i915/i830_metaops.c
new file mode 100644
index 0000000000..fb2ee12f41
--- /dev/null
+++ b/src/mesa/drivers/dri/i915/i830_metaops.c
@@ -0,0 +1,699 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "utils.h"
+
+#include "intel_screen.h"
+#include "intel_batchbuffer.h"
+#include "intel_ioctl.h"
+
+#include "i830_context.h"
+#include "i830_reg.h"
+
+/* A large amount of state doesn't need to be uploaded.
+ */
+#define ACTIVE (I830_UPLOAD_TEXBLEND(0) | \
+ I830_UPLOAD_STIPPLE | \
+ I830_UPLOAD_CTX | \
+ I830_UPLOAD_BUFFERS | \
+ I830_UPLOAD_TEX(0))
+
+
+#define SET_STATE( i830, STATE ) \
+do { \
+ i830->current->emitted &= ~ACTIVE; \
+ i830->current = &i830->STATE; \
+ i830->current->emitted &= ~ACTIVE; \
+} while (0)
+
+/* Operations where the 3D engine is decoupled temporarily from the
+ * current GL state and used for other purposes than simply rendering
+ * incoming triangles.
+ */
+static void set_initial_state( i830ContextPtr i830 )
+{
+ memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
+ i830->meta.active = ACTIVE;
+ i830->meta.emitted = 0;
+}
+
+
+static void set_no_depth_stencil_write( i830ContextPtr i830 )
+{
+ /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
+ */
+ i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
+
+
+ /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
+ */
+ i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
+
+ i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+/* Set stencil unit to replace always with the reference value.
+ */
+static void set_stencil_replace( i830ContextPtr i830,
+ GLuint s_mask,
+ GLuint s_clear)
+{
+ /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
+ */
+ i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
+
+
+ /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
+ */
+ i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
+
+ /* ctx->Driver.StencilMask( ctx, s_mask )
+ */
+ i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
+ i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
+ STENCIL_WRITE_MASK((s_mask&0xff)));
+
+ /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
+ */
+ i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
+ i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
+ (ENABLE_STENCIL_PARMS |
+ STENCIL_FAIL_OP(STENCILOP_REPLACE) |
+ STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) |
+ STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE));
+
+ /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_clear, ~0 )
+ */
+ i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
+ i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
+ STENCIL_TEST_MASK(0xff));
+
+ i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK |
+ ENABLE_STENCIL_TEST_FUNC_MASK);
+ i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
+ (ENABLE_STENCIL_REF_VALUE |
+ ENABLE_STENCIL_TEST_FUNC |
+ STENCIL_REF_VALUE((s_clear&0xff)) |
+ STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS));
+
+
+
+ i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+
+static void set_color_mask( i830ContextPtr i830, GLboolean state )
+{
+ const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
+ (1 << WRITEMASK_GREEN_SHIFT) |
+ (1 << WRITEMASK_BLUE_SHIFT) |
+ (1 << WRITEMASK_ALPHA_SHIFT));
+
+ if (state) {
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask;
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] |=
+ (i830->state.Ctx[I830_CTXREG_ENABLES_2] & mask);
+ }
+ else
+ i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= mask;
+
+ i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+/* Installs a one-stage passthrough texture blend pipeline. Is there
+ * more that can be done to turn off texturing?
+ */
+static void set_no_texture( i830ContextPtr i830 )
+{
+ i830->meta.TexBlendWordsUsed[0] =
+ i830SetBlend_GL1_2( i830, 0, GL_NONE, 0,
+ TEXBLENDARG_TEXEL0,
+ i830->meta.TexBlend[0], 0 );
+ i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
+ i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
+}
+
+/* Set up a single element blend stage for 'replace' texturing with no
+ * funny ops.
+ */
+static void enable_texture_blend_replace( i830ContextPtr i830,
+ GLenum format )
+{
+ i830->meta.TexBlendWordsUsed[0] =
+ i830SetBlend_GL1_2( i830, 0, GL_REPLACE, format,
+ TEXBLENDARG_TEXEL0,
+ i830->meta.TexBlend[0], 0 );
+ i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
+ i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
+
+/* fprintf(stderr, "%s: TexBlendWordsUsed[0]: %d\n", */
+/* __FUNCTION__, i830->meta.TexBlendWordsUsed[0]); */
+}
+
+
+
+/* Set up an arbitary piece of memory as a rectangular texture
+ * (including the front or back buffer).
+ */
+static void set_tex_rect_source( i830ContextPtr i830,
+ GLuint offset,
+ GLuint width,
+ GLuint height,
+ GLuint pitch,
+ GLuint textureFormat )
+{
+ GLint numLevels = 1;
+ GLuint *setup = i830->meta.Tex[0];
+
+ pitch *= i830->intel.intelScreen->cpp;
+
+/* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
+/* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
+
+ setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+ (LOAD_TEXTURE_MAP0 << 0) | 4);
+ setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset);
+ setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
+ ((width - 1) << TM0S1_WIDTH_SHIFT) |
+ textureFormat);
+ setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));
+ setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
+ setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
+ setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
+
+ setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
+ MAP_UNIT(0) |
+ ENABLE_TEXCOORD_PARAMS |
+ TEXCOORDS_ARE_IN_TEXELUNITS |
+ TEXCOORDTYPE_CARTESIAN |
+ ENABLE_ADDR_V_CNTL |
+ TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
+ ENABLE_ADDR_U_CNTL |
+ TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
+
+ i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
+}
+
+
+/* Select between front and back draw buffers.
+ */
+static void set_draw_offset( i830ContextPtr i830,
+ GLuint offset )
+{
+ i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset;
+ i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
+}
+
+/* Setup an arbitary draw format, useful for targeting
+ * texture or agp memory.
+ */
+static void set_draw_format( i830ContextPtr i830,
+ GLuint format,
+ GLuint depth_format)
+{
+ i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
+ DSTORG_VERT_BIAS(0x8) | /* .5 */
+ format |
+ DEPTH_IS_Z |
+ depth_format);
+}
+
+
+static void set_vertex_format( i830ContextPtr i830 )
+{
+ i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
+ VFT0_TEX_COUNT(1) |
+ VFT0_DIFFUSE |
+ VFT0_SPEC |
+ VFT0_XYZW);
+ i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD |
+ VFT1_TEX0_FMT(TEXCOORDFMT_2D) |
+ VFT1_TEX1_FMT(TEXCOORDFMT_2D) |
+ VFT1_TEX2_FMT(TEXCOORDFMT_2D) |
+ VFT1_TEX3_FMT(TEXCOORDFMT_2D));
+ i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+
+static void draw_quad(i830ContextPtr i830,
+ GLfloat x0, GLfloat x1,
+ GLfloat y0, GLfloat y1,
+ GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha,
+ GLfloat s0, GLfloat s1,
+ GLfloat t0, GLfloat t1 )
+{
+ GLuint vertex_size = 8;
+ GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
+ PRIM3D_TRIFAN,
+ 4*vertex_size,
+ vertex_size );
+ intelVertex tmp;
+ int i;
+
+
+/* fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
+/* __FUNCTION__, */
+/* x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
+
+
+ /* initial vertex, left bottom */
+ tmp.v.x = x0;
+ tmp.v.y = y0;
+ tmp.v.z = 1.0;
+ tmp.v.w = 1.0;
+ tmp.v.color.red = red;
+ tmp.v.color.green = green;
+ tmp.v.color.blue = blue;
+ tmp.v.color.alpha = alpha;
+ tmp.v.specular.red = 0;
+ tmp.v.specular.green = 0;
+ tmp.v.specular.blue = 0;
+ tmp.v.specular.alpha = 0;
+ tmp.v.u0 = s0;
+ tmp.v.v0 = t0;
+ for (i = 0 ; i < 8 ; i++)
+ vb[i] = tmp.ui[i];
+
+ /* right bottom */
+ vb += 8;
+ tmp.v.x = x1;
+ tmp.v.u0 = s1;
+ for (i = 0 ; i < 8 ; i++)
+ vb[i] = tmp.ui[i];
+
+ /* right top */
+ vb += 8;
+ tmp.v.y = y1;
+ tmp.v.v0 = t1;
+ for (i = 0 ; i < 8 ; i++)
+ vb[i] = tmp.ui[i];
+
+ /* left top */
+ vb += 8;
+ tmp.v.x = x0;
+ tmp.v.u0 = s0;
+ for (i = 0 ; i < 8 ; i++)
+ vb[i] = tmp.ui[i];
+
+/* fprintf(stderr, "%s: DV1: %x\n", */
+/* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
+}
+
+void
+i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
+ GLboolean all,
+ GLint cx, GLint cy, GLint cw, GLint ch)
+{
+ i830ContextPtr i830 = I830_CONTEXT( intel );
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ intelScreenPrivate *screen = intel->intelScreen;
+ int x0, y0, x1, y1;
+
+
+ SET_STATE( i830, meta );
+ set_initial_state( i830 );
+ set_no_texture( i830 );
+ set_vertex_format( i830 );
+
+ LOCK_HARDWARE(intel);
+
+ if(!all) {
+ x0 = cx;
+ y0 = cy;
+ x1 = x0 + cw;
+ y1 = y0 + ch;
+ } else {
+ x0 = 0;
+ y0 = 0;
+ x1 = x0 + dPriv->w;
+ y1 = y0 + dPriv->h;
+ }
+
+ /* Don't do any clipping to screen - these are window coordinates.
+ * The active cliprects will be applied as for any other geometry.
+ */
+
+ if(mask & DD_FRONT_LEFT_BIT) {
+ set_no_depth_stencil_write( i830 );
+ set_color_mask( i830, GL_TRUE );
+ set_draw_offset( i830, screen->frontOffset );
+ draw_quad(i830, x0, x1, y0, y1,
+ intel->clear_red, intel->clear_green,
+ intel->clear_blue, intel->clear_alpha,
+ 0, 0, 0, 0);
+ }
+
+ if(mask & DD_BACK_LEFT_BIT) {
+ set_no_depth_stencil_write( i830 );
+ set_color_mask( i830, GL_TRUE );
+ set_draw_offset( i830, screen->backOffset );
+
+ draw_quad(i830, x0, x1, y0, y1,
+ intel->clear_red, intel->clear_green,
+ intel->clear_blue, intel->clear_alpha,
+ 0, 0, 0, 0);
+ }
+
+ if(mask & DD_STENCIL_BIT) {
+ set_stencil_replace( i830,
+ intel->ctx.Stencil.WriteMask[0],
+ intel->ctx.Stencil.Clear);
+
+ set_color_mask( i830, GL_FALSE );
+ set_draw_offset( i830, screen->frontOffset );
+ draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
+ }
+
+ UNLOCK_HARDWARE(intel);
+
+ SET_STATE( i830, state );
+}
+
+
+
+
+GLboolean
+i830TryTextureReadPixels( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *pixels )
+{
+ i830ContextPtr i830 = I830_CONTEXT(ctx);
+ intelContextPtr intel = INTEL_CONTEXT(ctx);
+ intelScreenPrivate *screen = i830->intel.intelScreen;
+ GLint pitch = pack->RowLength ? pack->RowLength : width;
+ __DRIdrawablePrivate *dPriv = i830->intel.driDrawable;
+ int textureFormat;
+ GLenum glTextureFormat;
+ int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
+ int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels);
+ int destFormat, depthFormat, destPitch;
+ drm_clip_rect_t tmp;
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+
+ if ( ctx->_ImageTransferState ||
+ pack->SwapBytes ||
+ pack->LsbFirst ||
+ !pack->Invert) {
+ fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ switch (screen->fbFormat) {
+ case DV_PF_565:
+ textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
+ glTextureFormat = GL_RGB;
+ break;
+ case DV_PF_555:
+ textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
+ glTextureFormat = GL_RGBA;
+ break;
+ case DV_PF_8888:
+ textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
+ glTextureFormat = GL_RGBA;
+ break;
+ default:
+ fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__,
+ screen->fbFormat);
+ return GL_FALSE;
+ }
+
+
+ switch (type) {
+ case GL_UNSIGNED_SHORT_5_6_5:
+ if (format != GL_RGB) return GL_FALSE;
+ destFormat = COLR_BUF_RGB565;
+ depthFormat = DEPTH_FRMT_16_FIXED;
+ destPitch = pitch * 2;
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ if (format != GL_BGRA) return GL_FALSE;
+ destFormat = COLR_BUF_ARGB8888;
+ depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER;
+ destPitch = pitch * 4;
+ break;
+ default:
+ fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(type));
+ return GL_FALSE;
+ }
+
+ destFormat |= (0x02<<24);
+
+/* fprintf(stderr, "type: %s destFormat: %x\n", */
+/* _mesa_lookup_enum_by_nr(type), */
+/* destFormat); */
+
+ intelFlush( ctx );
+
+ SET_STATE( i830, meta );
+ set_initial_state( i830 );
+ set_no_depth_stencil_write( i830 );
+
+ LOCK_HARDWARE( intel );
+ {
+ intelWaitForIdle( intel ); /* required by GL */
+
+ if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
+ UNLOCK_HARDWARE( intel );
+ SET_STATE(i830, state);
+ fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
+ return GL_TRUE;
+ }
+
+#if 0
+ /* FIXME -- Just emit the correct state
+ */
+ if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,
+ destPitch) != 0) {
+ UNLOCK_HARDWARE( intel );
+ SET_STATE(i830, state);
+ fprintf(stderr, "%s: setparam failed\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+#endif
+
+
+ y = dPriv->h - y - height;
+ x += dPriv->x;
+ y += dPriv->y;
+
+
+ /* Set the frontbuffer up as a large rectangular texture.
+ */
+ set_tex_rect_source( i830,
+ src_offset,
+ screen->width,
+ screen->height,
+ screen->frontPitch,
+ textureFormat );
+
+
+ enable_texture_blend_replace( i830, glTextureFormat );
+
+
+ /* Set the 3d engine to draw into the agp memory
+ */
+
+ set_draw_offset( i830, destOffset );
+ set_draw_format( i830, destFormat, depthFormat );
+
+
+ /* Draw a single quad, no cliprects:
+ */
+ i830->intel.numClipRects = 1;
+ i830->intel.pClipRects = &tmp;
+ i830->intel.pClipRects[0].x1 = 0;
+ i830->intel.pClipRects[0].y1 = 0;
+ i830->intel.pClipRects[0].x2 = width;
+ i830->intel.pClipRects[0].y2 = height;
+
+ draw_quad( i830,
+ 0, width, 0, height,
+ 0, 255, 0, 0,
+ x, x+width, y, y+height );
+
+ intelWindowMoved( intel );
+ }
+ UNLOCK_HARDWARE( intel );
+ intelFinish( ctx ); /* required by GL */
+
+ SET_STATE( i830, state );
+ return GL_TRUE;
+}
+
+
+GLboolean
+i830TryTextureDrawPixels( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ intelContextPtr intel = INTEL_CONTEXT(ctx);
+ i830ContextPtr i830 = I830_CONTEXT(ctx);
+ GLint pitch = unpack->RowLength ? unpack->RowLength : width;
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ int textureFormat;
+ GLenum glTextureFormat;
+ int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
+ int src_offset = intelAgpOffsetFromVirtual( intel, pixels );
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ /* Todo -- upload images that aren't in agp space, then texture
+ * from them.
+ */
+
+ if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) {
+ fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ /* Todo -- don't want to clobber all the drawing state like we do
+ * for readpixels -- most of this state can be handled just fine.
+ */
+ if ( ctx->_ImageTransferState ||
+ unpack->SwapBytes ||
+ unpack->LsbFirst ||
+ ctx->Color.AlphaEnabled ||
+ ctx->Depth.Test ||
+ ctx->Fog.Enabled ||
+ ctx->Scissor.Enabled ||
+ ctx->Stencil.Enabled ||
+ !ctx->Color.ColorMask[0] ||
+ !ctx->Color.ColorMask[1] ||
+ !ctx->Color.ColorMask[2] ||
+ !ctx->Color.ColorMask[3] ||
+ ctx->Color.ColorLogicOpEnabled ||
+ ctx->Texture._EnabledUnits ||
+ ctx->Depth.OcclusionTest) {
+ fprintf(stderr, "%s: other tests failed\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ /* Todo -- remove these restrictions:
+ */
+ if (ctx->Pixel.ZoomX != 1.0F ||
+ ctx->Pixel.ZoomY != -1.0F)
+ return GL_FALSE;
+
+
+
+ switch (type) {
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ if (format != GL_BGRA) return GL_FALSE;
+ textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
+ glTextureFormat = GL_RGBA;
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ if (format != GL_RGB) return GL_FALSE;
+ textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
+ glTextureFormat = GL_RGB;
+ break;
+ case GL_UNSIGNED_SHORT_8_8_MESA:
+ if (format != GL_YCBCR_MESA) return GL_FALSE;
+ textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY
+/* | TM0S1_COLORSPACE_CONVERSION */
+ );
+ glTextureFormat = GL_YCBCR_MESA;
+ break;
+ case GL_UNSIGNED_SHORT_8_8_REV_MESA:
+ if (format != GL_YCBCR_MESA) return GL_FALSE;
+ textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL
+/* | TM0S1_COLORSPACE_CONVERSION */
+ );
+ glTextureFormat = GL_YCBCR_MESA;
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ if (format != GL_BGRA) return GL_FALSE;
+ textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
+ glTextureFormat = GL_RGBA;
+ break;
+ default:
+ fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ intelFlush( ctx );
+
+ SET_STATE( i830, meta );
+
+ LOCK_HARDWARE( intel );
+ {
+ intelWaitForIdle( intel ); /* required by GL */
+
+ y -= height; /* cope with pixel zoom */
+
+ if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
+ UNLOCK_HARDWARE( intel );
+ SET_STATE(i830, state);
+ fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
+ return GL_TRUE;
+ }
+
+
+ y = dPriv->h - y - height;
+
+ set_initial_state( i830 );
+
+ /* Set the pixel image up as a rectangular texture.
+ */
+ set_tex_rect_source( i830,
+ src_offset,
+ width,
+ height,
+ pitch, /* XXXX!!!! -- /2 sometimes */
+ textureFormat );
+
+
+ enable_texture_blend_replace( i830, glTextureFormat );
+
+
+ /* Draw to the current draw buffer:
+ */
+ set_draw_offset( i830, dst_offset );
+
+ /* Draw a quad, use regular cliprects
+ */
+/* fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
+
+ draw_quad( i830,
+ x, x+width, y, y+height,
+ 0, 255, 0, 0,
+ 0, width, 0, height );
+
+ intelWindowMoved( intel );
+ }
+ UNLOCK_HARDWARE( intel );
+ intelFinish( ctx ); /* required by GL */
+
+ SET_STATE(i830, state);
+
+ return GL_TRUE;
+}
+