static void do_draw_pix( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLint pitch, const void *pixels, GLuint planemask) { r200ContextPtr rmesa = R200_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; drm_clip_rect_t *box = dPriv->pClipRects; struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorDrawBuffers[0][0]; driRenderbuffer *drb = (driRenderbuffer *) rb; int nbox = dPriv->numClipRects; int i; int blit_format; int size; int src_offset = r200GartOffsetFromVirtual( rmesa, pixels ); int src_pitch = pitch * rmesa->r200Screen->cpp; if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); switch ( rmesa->r200Screen->cpp ) { case 2: blit_format = R200_CP_COLOR_FORMAT_RGB565; break; case 4: blit_format = R200_CP_COLOR_FORMAT_ARGB8888; break; default: return; } LOCK_HARDWARE( rmesa ); if (rmesa->store.cmd_used) r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); y -= height; /* cope with pixel zoom */ if (!clip_pixelrect(ctx, ctx->DrawBuffer, &x, &y, &width, &height, &size)) { UNLOCK_HARDWARE( rmesa ); return; } y = dPriv->h - y - height; /* convert from gl to hardware coords */ x += dPriv->x; y += dPriv->y; r200EmitWait( rmesa, RADEON_WAIT_3D ); for (i = 0 ; i < nbox ; i++ ) { GLint bx = box[i].x1; GLint by = box[i].y1; GLint bw = box[i].x2 - bx; GLint bh = box[i].y2 - by; if (bx < x) bw -= x - bx, bx = x; if (by < y) bh -= y - by, by = y; if (bx + bw > x + width) bw = x + width - bx; if (by + bh > y + height) bh = y + height - by; if (bw <= 0) continue; if (bh <= 0) continue; r200EmitBlit( rmesa, blit_format, src_pitch, src_offset, drb->pitch * drb->cpp, drb->offset + rmesa->r200Screen->fbLocation, bx - x, by - y, bx, by, bw, bh ); } r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); r200WaitForIdleLocked( rmesa ); /* required by GL */ UNLOCK_HARDWARE( rmesa ); }
static void r200UploadGARTClientSubImage( r200ContextPtr rmesa, r200TexObjPtr t, struct gl_texture_image *texImage, GLint hwlevel, GLint x, GLint y, GLint width, GLint height ) { const struct gl_texture_format *texFormat = texImage->TexFormat; GLuint srcPitch, dstPitch; int blit_format; int srcOffset; /* * XXX it appears that we always upload the full image, not a subimage. * I.e. x==0, y==0, width=texWidth, height=texWidth. If this is ever * changed, the src pitch will have to change. */ switch ( texFormat->TexelBytes ) { case 1: blit_format = R200_CP_COLOR_FORMAT_CI8; srcPitch = t->image[0][0].width * texFormat->TexelBytes; dstPitch = t->image[0][0].width * texFormat->TexelBytes; break; case 2: blit_format = R200_CP_COLOR_FORMAT_RGB565; srcPitch = t->image[0][0].width * texFormat->TexelBytes; dstPitch = t->image[0][0].width * texFormat->TexelBytes; break; case 4: blit_format = R200_CP_COLOR_FORMAT_ARGB8888; srcPitch = t->image[0][0].width * texFormat->TexelBytes; dstPitch = t->image[0][0].width * texFormat->TexelBytes; break; default: return; } t->image[0][hwlevel].data = texImage->Data; srcOffset = r200GartOffsetFromVirtual( rmesa, texImage->Data ); assert( srcOffset != ~0 ); /* Don't currently need to cope with small pitches? */ width = texImage->Width; height = texImage->Height; r200EmitWait( rmesa, RADEON_WAIT_3D ); r200EmitBlit( rmesa, blit_format, srcPitch, srcOffset, dstPitch, t->bufAddr, x, y, t->image[0][hwlevel].x + x, t->image[0][hwlevel].y + y, width, height ); r200EmitWait( rmesa, RADEON_WAIT_2D ); }
static GLboolean r200TryReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid *pixels ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); GLint pitch = pack->RowLength ? pack->RowLength : width; GLint blit_format; GLuint cpp = rmesa->r200Screen->cpp; GLint size = width * height * cpp; if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); /* Only accelerate reading to GART buffers. */ if ( !r200IsGartMemory(rmesa, pixels, pitch * height * rmesa->r200Screen->cpp ) ) { if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: dest not GART\n", __FUNCTION__); return GL_FALSE; } /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from * blitter: */ if (!pack->Invert) { if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); return GL_FALSE; } if (!check_color(ctx, type, format, pack, pixels, size, pitch)) return GL_FALSE; switch ( rmesa->r200Screen->cpp ) { case 4: blit_format = R200_CP_COLOR_FORMAT_ARGB8888; break; default: return GL_FALSE; } /* Although the blits go on the command buffer, need to do this and * fire with lock held to guarentee cliprects and drawOffset are * correct. * * This is an unusual situation however, as the code which flushes * a full command buffer expects to be called unlocked. As a * workaround, immediately flush the buffer on aquiring the lock. */ LOCK_HARDWARE( rmesa ); if (rmesa->store.cmd_used) r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, &size)) { UNLOCK_HARDWARE( rmesa ); if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s totally clipped -- nothing to do\n", __FUNCTION__); return GL_TRUE; } { __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; driRenderbuffer *drb = (driRenderbuffer *) ctx->ReadBuffer->_ColorReadBuffer; int nbox = dPriv->numClipRects; int src_offset = drb->offset + rmesa->r200Screen->fbLocation; int src_pitch = drb->pitch * drb->cpp; int dst_offset = r200GartOffsetFromVirtual( rmesa, pixels ); int dst_pitch = pitch * rmesa->r200Screen->cpp; drm_clip_rect_t *box = dPriv->pClipRects; int i; r200EmitWait( rmesa, RADEON_WAIT_3D ); y = dPriv->h - y - height; x += dPriv->x; y += dPriv->y; if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", src_pitch, dst_pitch); for (i = 0 ; i < nbox ; i++) { GLint bx = box[i].x1; GLint by = box[i].y1; GLint bw = box[i].x2 - bx; GLint bh = box[i].y2 - by; if (bx < x) bw -= x - bx, bx = x; if (by < y) bh -= y - by, by = y; if (bx + bw > x + width) bw = x + width - bx; if (by + bh > y + height) bh = y + height - by; if (bw <= 0) continue; if (bh <= 0) continue; r200EmitBlit( rmesa, blit_format, src_pitch, src_offset, dst_pitch, dst_offset, bx, by, bx - x, by - y, bw, bh ); } r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); } UNLOCK_HARDWARE( rmesa ); r200Finish( ctx ); /* required by GL */ return GL_TRUE; }
static void r200UploadRectSubImage( r200ContextPtr rmesa, r200TexObjPtr t, struct gl_texture_image *texImage, GLint x, GLint y, GLint width, GLint height ) { const struct gl_texture_format *texFormat = texImage->TexFormat; int blit_format, dstPitch, done; switch ( texFormat->TexelBytes ) { case 1: blit_format = R200_CP_COLOR_FORMAT_CI8; break; case 2: blit_format = R200_CP_COLOR_FORMAT_RGB565; break; case 4: blit_format = R200_CP_COLOR_FORMAT_ARGB8888; break; default: return; } t->image[0][0].data = texImage->Data; /* Currently don't need to cope with small pitches. */ width = texImage->Width; height = texImage->Height; dstPitch = t->pp_txpitch + 32; if (rmesa->prefer_gart_client_texturing && texImage->IsClientData) { /* In this case, could also use GART texturing. This is * currently disabled, but has been tested & works. */ if ( !t->image_override ) t->pp_txoffset = r200GartOffsetFromVirtual( rmesa, texImage->Data ); t->pp_txpitch = texImage->RowStride * texFormat->TexelBytes - 32; if (R200_DEBUG & DEBUG_TEXTURE) fprintf(stderr, "Using GART texturing for rectangular client texture\n"); /* Release FB memory allocated for this image: */ /* FIXME This may not be correct as driSwapOutTextureObject sets * FIXME dirty_images. It may be fine, though. */ if ( t->base.memBlock ) { driSwapOutTextureObject( (driTextureObject *) t ); } } else if (texImage->IsClientData) { /* Data already in GART memory, with usable pitch. */ GLuint srcPitch; srcPitch = texImage->RowStride * texFormat->TexelBytes; r200EmitBlit( rmesa, blit_format, srcPitch, r200GartOffsetFromVirtual( rmesa, texImage->Data ), dstPitch, t->bufAddr, 0, 0, 0, 0, width, height ); } else { /* Data not in GART memory, or bad pitch. */ for (done = 0; done < height ; ) { struct r200_dma_region region; int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch ); int src_pitch; char *tex; src_pitch = texImage->RowStride * texFormat->TexelBytes; tex = (char *)texImage->Data + done * src_pitch; memset(®ion, 0, sizeof(region)); r200AllocDmaRegion( rmesa, ®ion, lines * dstPitch, 1024 ); /* Copy texdata to dma: */ if (0) fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n", __FUNCTION__, src_pitch, dstPitch); if (src_pitch == dstPitch) { memcpy( region.address + region.start, tex, lines * src_pitch ); } else { char *buf = region.address + region.start; int i; for (i = 0 ; i < lines ; i++) { memcpy( buf, tex, src_pitch ); buf += dstPitch; tex += src_pitch; } } r200EmitWait( rmesa, RADEON_WAIT_3D ); /* Blit to framebuffer */ r200EmitBlit( rmesa, blit_format, dstPitch, GET_START( ®ion ), dstPitch | (t->tile_bits >> 16), t->bufAddr, 0, 0, 0, done, width, lines ); r200EmitWait( rmesa, RADEON_WAIT_2D ); r200ReleaseDmaRegion( rmesa, ®ion, __FUNCTION__ ); done += lines; } } }