void i810Fallback( i810ContextPtr imesa, GLuint bit, GLboolean mode ) { GLcontext *ctx = imesa->glCtx; TNLcontext *tnl = TNL_CONTEXT(ctx); GLuint oldfallback = imesa->Fallback; if (0) fprintf(stderr, "%s old %x bit %x mode %d\n", __FUNCTION__, imesa->Fallback, bit, mode ); if (mode) { imesa->Fallback |= bit; if (oldfallback == 0) { I810_FIREVERTICES(imesa); if (I810_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "ENTER FALLBACK %s\n", getFallbackString( bit )); _swsetup_Wakeup( ctx ); imesa->RenderIndex = ~0; } } else { imesa->Fallback &= ~bit; if (oldfallback == bit) { _swrast_flush( ctx ); if (I810_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit )); tnl->Driver.Render.Start = i810RenderStart; tnl->Driver.Render.PrimitiveNotify = i810RenderPrimitive; tnl->Driver.Render.Finish = i810RenderFinish; tnl->Driver.Render.BuildVertices = i810BuildVertices; imesa->new_state |= (_I810_NEW_RENDERSTATE|_I810_NEW_VERTEX); } } }
static void i810TexImage2D( GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ) { driTextureObject *t = (driTextureObject *) texObj->DriverData; if (t) { I810_FIREVERTICES( I810_CONTEXT(ctx) ); driSwapOutTextureObject( t ); } else { t = (driTextureObject *) i810AllocTexObj( ctx, texObj ); if (!t) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; } } _mesa_store_teximage2d( ctx, target, level, internalFormat, width, height, border, format, type, pixels, packing, texObj, texImage ); }
/* Move locking out to get reasonable span performance. */ void i810SpanRenderStart( GLcontext *ctx ) { i810ContextPtr imesa = I810_CONTEXT(ctx); I810_FIREVERTICES(imesa); LOCK_HARDWARE(imesa); i810RegetLockQuiescent( imesa ); }
/* This waits for *everybody* to finish rendering -- overkill. */ void i810DmaFinish( i810ContextPtr imesa ) { I810_FIREVERTICES( imesa ); LOCK_HARDWARE( imesa ); i810RegetLockQuiescent( imesa ); UNLOCK_HARDWARE( imesa ); }
static void i810DeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) { driTextureObject * t = (driTextureObject *) tObj->DriverData; if (t) { i810ContextPtr imesa = I810_CONTEXT( ctx ); if (imesa) I810_FIREVERTICES( imesa ); driDestroyTextureObject( t ); } }
static void i810Scissor( struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h ) { i810ContextPtr imesa = I810_CONTEXT(ctx); if (ctx->Scissor.Enabled) { I810_FIREVERTICES(imesa); /* don't pipeline cliprect changes */ imesa->upload_cliprects = GL_TRUE; } imesa->scissor_rect.x1 = x; imesa->scissor_rect.y1 = imesa->driDrawable->h - (y + h); imesa->scissor_rect.x2 = x + w; imesa->scissor_rect.y2 = imesa->driDrawable->h - y; }
void i810DrawBuffer(GLcontext *ctx, GLenum mode ) { i810ContextPtr imesa = I810_CONTEXT(ctx); int front = 0; /* * _DrawDestMask is easier to cope with than <mode>. */ switch ( ctx->Color._DrawDestMask[0] ) { case DD_FRONT_LEFT_BIT: front = 1; break; case DD_BACK_LEFT_BIT: front = 0; break; default: /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_TRUE ); return; } if ( imesa->sarea->pf_current_page == 1 ) front ^= 1; FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_FALSE ); I810_FIREVERTICES(imesa); I810_STATECHANGE(imesa, I810_UPLOAD_BUFFERS); if (front) { imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits); i810XMesaSetFrontClipRects( imesa ); } else { imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits); i810XMesaSetBackClipRects( imesa ); } /* We want to update the s/w rast state too so that r200SetBuffer() * gets called. */ _swrast_DrawBuffer(ctx, mode); }
void i810DrawBuffer(struct gl_context *ctx, GLenum mode ) { i810ContextPtr imesa = I810_CONTEXT(ctx); int front = 0; if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_TRUE ); return; } switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0]) { case BUFFER_FRONT_LEFT: front = 1; break; case BUFFER_BACK_LEFT: front = 0; break; default: FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_TRUE ); return; } if ( imesa->sarea->pf_current_page == 1 ) front ^= 1; FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_FALSE ); I810_FIREVERTICES(imesa); I810_STATECHANGE(imesa, I810_UPLOAD_BUFFERS); if (front) { imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits); i810XMesaSetFrontClipRects( imesa ); } else { imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits); i810XMesaSetBackClipRects( imesa ); } }
/* * Copy the back buffer to the front buffer. */ void i810CopyBuffer( const __DRIdrawable *dPriv ) { i810ContextPtr imesa; drm_clip_rect_t *pbox; int nbox, i, tmp; assert(dPriv); assert(dPriv->driContextPriv); assert(dPriv->driContextPriv->driverPrivate); imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate; I810_FIREVERTICES( imesa ); LOCK_HARDWARE( imesa ); pbox = (drm_clip_rect_t *)dPriv->pClipRects; nbox = dPriv->numClipRects; for (i = 0 ; i < nbox ; ) { int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, dPriv->numClipRects); drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes; imesa->sarea->nbox = nr - i; for ( ; i < nr ; i++) *b++ = pbox[i]; drmCommandNone(imesa->driFd, DRM_I810_SWAP); } tmp = GET_ENQUEUE_AGE(imesa); UNLOCK_HARDWARE( imesa ); /* multiarb will suck the life out of the server without this throttle: */ if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) { i810WaitAge(imesa, imesa->lastSwap); } imesa->lastSwap = tmp; imesa->upload_cliprects = GL_TRUE; }
/* * XXX implement when full-screen extension is done. */ void i810PageFlip( const __DRIdrawable *dPriv ) { i810ContextPtr imesa; int tmp, ret; assert(dPriv); assert(dPriv->driContextPriv); assert(dPriv->driContextPriv->driverPrivate); imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate; I810_FIREVERTICES( imesa ); LOCK_HARDWARE( imesa ); if (dPriv->pClipRects) { memcpy(&(imesa->sarea->boxes[0]), &(dPriv->pClipRects[0]), sizeof(drm_clip_rect_t)); imesa->sarea->nbox = 1; } ret = drmCommandNone(imesa->driFd, DRM_I810_FLIP); if (ret) { fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); UNLOCK_HARDWARE( imesa ); exit(1); } tmp = GET_ENQUEUE_AGE(imesa); UNLOCK_HARDWARE( imesa ); /* multiarb will suck the life out of the server without this throttle: */ if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) { i810WaitAge(imesa, imesa->lastSwap); } /* i810SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer );*/ i810DrawBuffer( imesa->glCtx, imesa->glCtx->Color.DrawBuffer[0] ); imesa->upload_cliprects = GL_TRUE; imesa->lastSwap = tmp; return; }
static void i810TexSubImage2D( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ) { driTextureObject *t = (driTextureObject *)texObj->DriverData; if (t) { I810_FIREVERTICES( I810_CONTEXT(ctx) ); driSwapOutTextureObject( t ); } _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, height, format, type, pixels, packing, texObj, texImage); }
static GLboolean enable_tex_common( struct gl_context *ctx, GLuint unit ) { i810ContextPtr imesa = I810_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; if (tObj->Image[0][tObj->BaseLevel]->Border > 0) { return GL_FALSE; } /* Upload teximages (not pipelined) */ if (t->base.dirty_images[0]) { I810_FIREVERTICES(imesa); i810SetTexImages( imesa, tObj ); if (!t->base.memBlock) { return GL_FALSE; } } /* Update state if this is a different texture object to last * time. */ if (imesa->CurrentTexObj[unit] != t) { I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); imesa->CurrentTexObj[unit] = t; t->base.bound |= (1U << unit); /* XXX: should be locked */ driUpdateTextureLRU( (driTextureObject *) t ); } imesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; return GL_TRUE; }
/* ============================================================= */ static void i810Enable(struct gl_context *ctx, GLenum cap, GLboolean state) { i810ContextPtr imesa = I810_CONTEXT(ctx); switch(cap) { case GL_ALPHA_TEST: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B1] &= ~B1_ALPHA_TEST_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_ALPHA_TEST_ENABLE; break; case GL_BLEND: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B1] &= ~B1_BLEND_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_BLEND_ENABLE; /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled. */ FALLBACK( imesa, I810_FALLBACK_LOGICOP, (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY)); break; case GL_DEPTH_TEST: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B1] &= ~B1_Z_TEST_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_Z_TEST_ENABLE; break; case GL_SCISSOR_TEST: /* XXX without these next two lines, conform's scissor test fails */ I810_STATECHANGE(imesa, I810_UPLOAD_CTX); I810_STATECHANGE(imesa, I810_UPLOAD_BUFFERS); I810_FIREVERTICES(imesa); /* don't pipeline cliprect changes */ imesa->upload_cliprects = GL_TRUE; imesa->scissor = state; break; case GL_POLYGON_STIPPLE: if (imesa->stipple_in_hw && imesa->reduced_primitive == GL_TRIANGLES) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_ST1] &= ~ST1_ENABLE; if (state) imesa->Setup[I810_CTXREG_ST1] |= ST1_ENABLE; } break; case GL_LINE_SMOOTH: /* Need to fatten the lines by .5, or they disappear... */ if (imesa->reduced_primitive == GL_LINES) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_0_5; if (state) { imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; imesa->Setup[I810_CTXREG_LCS] |= LCS_LINEWIDTH_0_5; } } break; case GL_POINT_SMOOTH: if (imesa->reduced_primitive == GL_POINTS) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_0_5; if (state) { imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; imesa->Setup[I810_CTXREG_LCS] |= LCS_LINEWIDTH_0_5; } } break; case GL_POLYGON_SMOOTH: if (imesa->reduced_primitive == GL_TRIANGLES) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; if (state) imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; } break; case GL_FOG: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B1] &= ~B1_FOG_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_FOG_ENABLE; break; case GL_CULL_FACE: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK; if (state) imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsCullMode; else imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE; break; case GL_TEXTURE_2D: case GL_TEXTURE_RECTANGLE_NV: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); if (ctx->Texture.CurrentUnit == 0) { imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL0_ENABLE; if (state) imesa->Setup[I810_CTXREG_MT] |= MT_TEXEL0_ENABLE; } else { imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL1_ENABLE; if (state) imesa->Setup[I810_CTXREG_MT] |= MT_TEXEL1_ENABLE; } break; case GL_COLOR_LOGIC_OP: FALLBACK( imesa, I810_FALLBACK_LOGICOP, (state && ctx->Color.LogicOp != GL_COPY)); break; case GL_STENCIL_TEST: FALLBACK( imesa, I810_FALLBACK_STENCIL, state ); break; default: ; } }
static void i810TexParameter( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLenum pname, const GLfloat *params ) { i810ContextPtr imesa = I810_CONTEXT(ctx); i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData; if (!t) return; if ( target != GL_TEXTURE_2D ) return; /* Can't do the update now as we don't know whether to flush * vertices or not. Setting imesa->new_state means that * i810UpdateTextureState() will be called before any triangles are * rendered. If a statechange has occurred, it will be detected at * that point, and buffered vertices flushed. */ switch (pname) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: { GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias; i810SetTexFilter( imesa, t, tObj->MinFilter, tObj->MagFilter, bias ); } break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: i810SetTexWrapping( t, tObj->WrapS, tObj->WrapT ); break; case GL_TEXTURE_BORDER_COLOR: i810SetTexBorderColor( t, tObj->_BorderChan ); break; case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MAX_LOD: /* This isn't the most efficient solution but there doesn't appear to * be a nice alternative for Radeon. Since there's no LOD clamping, * we just have to rely on loading the right subset of mipmap levels * to simulate a clamped LOD. */ I810_FIREVERTICES( I810_CONTEXT(ctx) ); driSwapOutTextureObject( (driTextureObject *) t ); break; default: return; } if (t == imesa->CurrentTexObj[0]) { I810_STATECHANGE( imesa, I810_UPLOAD_TEX0 ); } if (t == imesa->CurrentTexObj[1]) { I810_STATECHANGE( imesa, I810_UPLOAD_TEX1 ); } }
static void i810Flush( struct gl_context *ctx ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); I810_FIREVERTICES( imesa ); }
static void i810Clear( struct gl_context *ctx, GLbitfield mask ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); __DRIdrawable *dPriv = imesa->driDrawable; const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask[0]); drmI810Clear clear; unsigned int i; clear.flags = 0; clear.clear_color = imesa->ClearColor; clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE); I810_FIREVERTICES( imesa ); if ((mask & BUFFER_BIT_FRONT_LEFT) && colorMask == ~0U) { clear.flags |= I810_FRONT; mask &= ~BUFFER_BIT_FRONT_LEFT; } if ((mask & BUFFER_BIT_BACK_LEFT) && colorMask == ~0U) { clear.flags |= I810_BACK; mask &= ~BUFFER_BIT_BACK_LEFT; } if (mask & BUFFER_BIT_DEPTH) { if (ctx->Depth.Mask) clear.flags |= I810_DEPTH; mask &= ~BUFFER_BIT_DEPTH; } if (clear.flags) { GLint cx, cy, cw, ch; LOCK_HARDWARE( imesa ); /* compute region after locking: */ cx = ctx->DrawBuffer->_Xmin; cy = ctx->DrawBuffer->_Ymin; cw = ctx->DrawBuffer->_Xmax - cx; ch = ctx->DrawBuffer->_Ymax - cy; /* flip top to bottom */ cy = dPriv->h-cy-ch; cx += imesa->drawX; cy += imesa->drawY; for (i = 0 ; i < imesa->numClipRects ; ) { unsigned int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, imesa->numClipRects); drm_clip_rect_t *box = imesa->pClipRects; drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes; int n = 0; if (cw != dPriv->w || ch != dPriv->h) { /* clear sub region */ for ( ; i < nr ; i++) { GLint x = box[i].x1; GLint y = box[i].y1; GLint w = box[i].x2 - x; GLint h = box[i].y2 - y; if (x < cx) w -= cx - x, x = cx; if (y < cy) h -= cy - y, y = cy; if (x + w > cx + cw) w = cx + cw - x; if (y + h > cy + ch) h = cy + ch - y; if (w <= 0) continue; if (h <= 0) continue; b->x1 = x; b->y1 = y; b->x2 = x + w; b->y2 = y + h; b++; n++; } } else { /* clear whole buffer */ for ( ; i < nr ; i++) { *b++ = box[i]; n++; } } imesa->sarea->nbox = n; drmCommandWrite(imesa->driFd, DRM_I810_CLEAR, &clear, sizeof(drmI810Clear)); } UNLOCK_HARDWARE( imesa ); imesa->upload_cliprects = GL_TRUE; } if (mask) _swrast_Clear( ctx, mask ); }