/* Allocates a region from rmesa->dma.current. If there isn't enough * space in current, grab a new buffer (and discard what was left of current) */ void r200AllocDmaRegion( r200ContextPtr rmesa, struct r200_dma_region *region, int bytes, int alignment ) { if (R200_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s %d\n", __FUNCTION__, bytes); if (rmesa->dma.flush) rmesa->dma.flush( rmesa ); if (region->buf) r200ReleaseDmaRegion( rmesa, region, __FUNCTION__ ); alignment--; rmesa->dma.current.start = rmesa->dma.current.ptr = (rmesa->dma.current.ptr + alignment) & ~alignment; if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) r200RefillCurrentDmaRegion( rmesa ); region->start = rmesa->dma.current.start; region->ptr = rmesa->dma.current.start; region->end = rmesa->dma.current.start + bytes; region->address = rmesa->dma.current.address; region->buf = rmesa->dma.current.buf; region->buf->refcount++; rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */ rmesa->dma.current.start = rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7; assert( rmesa->dma.current.ptr <= rmesa->dma.current.end ); }
void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs ) { GLuint unit; r200ContextPtr rmesa = R200_CONTEXT( ctx ); /* if (R200_DEBUG & DEBUG_VERTS) */ /* _tnl_print_vert_flags( __FUNCTION__, newinputs ); */ if (newinputs & VERT_BIT_POS) r200ReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ ); if (newinputs & VERT_BIT_NORMAL) r200ReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ ); if (newinputs & VERT_BIT_FOG) r200ReleaseDmaRegion( rmesa, &rmesa->tcl.fog, __FUNCTION__ ); if (newinputs & VERT_BIT_COLOR0) r200ReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ ); if (newinputs & VERT_BIT_COLOR1) r200ReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ ); for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) { if (newinputs & VERT_BIT_TEX(unit)) r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[unit], __FUNCTION__ ); } }
static void transition_to_hwtnl( GLcontext *ctx ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); _tnl_need_projected_coords( ctx, GL_FALSE ); r200UpdateMaterial( ctx ); tnl->Driver.NotifyMaterialChange = r200UpdateMaterial; if ( rmesa->dma.flush ) rmesa->dma.flush( rmesa ); rmesa->dma.flush = NULL; if (rmesa->swtcl.indexed_verts.buf) r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ ); R200_STATECHANGE( rmesa, vap ); rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE; rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_FORCE_W_TO_ONE; if (ctx->VertexProgram._Enabled) { rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE; } if ( ((rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK) == R200_FOG_USE_SPEC_ALPHA) && (ctx->Fog.FogCoordinateSource == GL_FOG_COORD )) { R200_STATECHANGE( rmesa, ctx ); rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK; rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_VTX_FOG; } R200_STATECHANGE( rmesa, vte ); rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT); rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT; if (R200_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "R200 end tcl fallback\n"); }
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; } } }
/* Destroy the Mesa and driver specific context data. */ void r200DestroyContext( __DRIcontextPrivate *driContextPriv ) { GET_CURRENT_CONTEXT(ctx); r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate; r200ContextPtr current = ctx ? R200_CONTEXT(ctx) : NULL; /* check if we're deleting the currently bound context */ if (rmesa == current) { R200_FIREVERTICES( rmesa ); _mesa_make_current(NULL, NULL, NULL); } /* Free r200 context resources */ assert(rmesa); /* should never be null */ if ( rmesa ) { GLboolean release_texture_heaps; release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1); _swsetup_DestroyContext( rmesa->glCtx ); _tnl_DestroyContext( rmesa->glCtx ); _vbo_DestroyContext( rmesa->glCtx ); _swrast_DestroyContext( rmesa->glCtx ); r200DestroySwtcl( rmesa->glCtx ); r200ReleaseArrays( rmesa->glCtx, ~0 ); if (rmesa->dma.current.buf) { r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ ); r200FlushCmdBuf( rmesa, __FUNCTION__ ); } if (rmesa->state.scissor.pClipRects) { FREE(rmesa->state.scissor.pClipRects); rmesa->state.scissor.pClipRects = NULL; } if ( release_texture_heaps ) { /* This share group is about to go away, free our private * texture object data. */ int i; for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) { driDestroyTextureHeap( rmesa->texture_heaps[ i ] ); rmesa->texture_heaps[ i ] = NULL; } assert( is_empty_list( & rmesa->swapped ) ); } /* free the Mesa context */ rmesa->glCtx->DriverCtx = NULL; _mesa_destroy_context( rmesa->glCtx ); /* free the option cache */ driDestroyOptionCache (&rmesa->optionCache); FREE( rmesa ); } }
void r200RefillCurrentDmaRegion( r200ContextPtr rmesa ) { struct r200_dma_buffer *dmabuf; int fd = rmesa->dri.fd; int index = 0; int size = 0; drmDMAReq dma; int ret; if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) fprintf(stderr, "%s\n", __FUNCTION__); if (rmesa->dma.flush) { rmesa->dma.flush( rmesa ); } if (rmesa->dma.current.buf) r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ ); if (rmesa->dma.nr_released_bufs > 4) r200FlushCmdBuf( rmesa, __FUNCTION__ ); dma.context = rmesa->dri.hwContext; dma.send_count = 0; dma.send_list = NULL; dma.send_sizes = NULL; dma.flags = 0; dma.request_count = 1; dma.request_size = RADEON_BUFFER_SIZE; dma.request_list = &index; dma.request_sizes = &size; dma.granted_count = 0; LOCK_HARDWARE(rmesa); /* no need to validate */ while (1) { ret = drmDMA( fd, &dma ); if (ret == 0) break; if (rmesa->dma.nr_released_bufs) { r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); } if (rmesa->do_usleeps) { UNLOCK_HARDWARE( rmesa ); DO_USLEEP( 1 ); LOCK_HARDWARE( rmesa ); } } UNLOCK_HARDWARE(rmesa); if (R200_DEBUG & DEBUG_DMA) fprintf(stderr, "Allocated buffer %d\n", index); dmabuf = CALLOC_STRUCT( r200_dma_buffer ); dmabuf->buf = &rmesa->r200Screen->buffers->list[index]; dmabuf->refcount = 1; rmesa->dma.current.buf = dmabuf; rmesa->dma.current.address = dmabuf->buf->address; rmesa->dma.current.end = dmabuf->buf->total; rmesa->dma.current.start = 0; rmesa->dma.current.ptr = 0; }
static void flush_prims( r200ContextPtr rmesa ) { int i,j; struct r200_dma_region tmp = rmesa->dma.current; tmp.buf->refcount++; tmp.aos_size = rmesa->vb.vertex_size; tmp.aos_stride = rmesa->vb.vertex_size; tmp.aos_start = GET_START(&tmp); rmesa->dma.current.ptr = rmesa->dma.current.start += (rmesa->vb.initial_counter - rmesa->vb.counter) * rmesa->vb.vertex_size * 4; rmesa->tcl.vertex_format = rmesa->vb.vtxfmt_0; rmesa->tcl.aos_components[0] = &tmp; rmesa->tcl.nr_aos_components = 1; rmesa->dma.flush = NULL; /* Optimize the primitive list: */ if (rmesa->vb.nrprims > 1) { for (j = 0, i = 1 ; i < rmesa->vb.nrprims; i++) { int pj = rmesa->vb.primlist[j].prim & 0xf; int pi = rmesa->vb.primlist[i].prim & 0xf; if (pj == pi && discreet_gl_prim[pj] && rmesa->vb.primlist[i].start == rmesa->vb.primlist[j].end) { rmesa->vb.primlist[j].end = rmesa->vb.primlist[i].end; } else { j++; if (j != i) rmesa->vb.primlist[j] = rmesa->vb.primlist[i]; } } rmesa->vb.nrprims = j+1; } if (rmesa->vb.vtxfmt_0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] || rmesa->vb.vtxfmt_1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) { R200_STATECHANGE( rmesa, vtx ); rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = rmesa->vb.vtxfmt_0; rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = rmesa->vb.vtxfmt_1; } for (i = 0 ; i < rmesa->vb.nrprims; i++) { if (R200_DEBUG & DEBUG_PRIMS) fprintf(stderr, "vtxfmt prim %d: %s %d..%d\n", i, _mesa_lookup_enum_by_nr( rmesa->vb.primlist[i].prim & PRIM_MODE_MASK ), rmesa->vb.primlist[i].start, rmesa->vb.primlist[i].end); if (rmesa->vb.primlist[i].start < rmesa->vb.primlist[i].end) r200EmitPrimitive( rmesa->glCtx, rmesa->vb.primlist[i].start, rmesa->vb.primlist[i].end, rmesa->vb.primlist[i].prim ); } rmesa->vb.nrprims = 0; r200ReleaseDmaRegion( rmesa, &tmp, __FUNCTION__ ); }