static void init_fs_constbuf( void ) { struct pipe_resource templat; struct pipe_box box; templat.target = PIPE_BUFFER; templat.format = PIPE_FORMAT_R8_UNORM; templat.width0 = sizeof(constants1); templat.height0 = 1; templat.depth0 = 1; templat.array_size = 1; templat.last_level = 0; templat.nr_samples = 1; templat.bind = PIPE_BIND_CONSTANT_BUFFER; constbuf1 = screen->resource_create(screen, &templat); if (constbuf1 == NULL) exit(4); constbuf2 = screen->resource_create(screen, &templat); if (constbuf2 == NULL) exit(4); { u_box_2d(0,0,sizeof(constants1),1, &box); ctx->transfer_inline_write(ctx, constbuf1, 0, PIPE_TRANSFER_WRITE, &box, constants1, sizeof constants1, sizeof constants1); pipe_set_constant_buffer(ctx, PIPE_SHADER_GEOMETRY, 0, constbuf1); } { u_box_2d(0,0,sizeof(constants2),1, &box); ctx->transfer_inline_write(ctx, constbuf2, 0, PIPE_TRANSFER_WRITE, &box, constants2, sizeof constants2, sizeof constants2); pipe_set_constant_buffer(ctx, PIPE_SHADER_GEOMETRY, 1, constbuf2); } }
static void ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height) { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap); exa_debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n", srcX, srcY, dstX, dstY, width, height); debug_assert(priv == exa->copy.dst); (void) priv; if (exa->copy.use_surface_copy) { struct pipe_box src_box; u_box_2d(srcX, srcY, width, height, &src_box); exa->pipe->resource_copy_region( exa->pipe, exa->copy.dst->tex, 0, dstX, dstY, 0, exa->copy.src->tex, 0, &src_box); } else { renderer_copy_pixmap(exa->renderer, dstX, dstY, srcX, srcY, width, height, exa->copy.src_texture->width0, exa->copy.src_texture->height0); } }
/** * Return information about the depth buffer associated with an OSMesa context. * Input: c - the OSMesa context * Output: width, height - size of buffer in pixels * bytesPerValue - bytes per depth value (2 or 4) * buffer - pointer to depth buffer values * Return: GL_TRUE or GL_FALSE to indicate success or failure. */ GLAPI GLboolean GLAPIENTRY OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height, GLint *bytesPerValue, void **buffer) { struct osmesa_buffer *osbuffer = c->current_buffer; struct pipe_context *pipe = c->stctx->pipe; struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL]; struct pipe_transfer *transfer = NULL; struct pipe_box box; /* * Note: we can't really implement this function with gallium as * we did for swrast. We can't just map the resource and leave it * mapped (and there's no OSMesaUnmapDepthBuffer() function) so * we unmap the buffer here and return a 'stale' pointer. This should * actually be OK in most cases where the caller of this function * immediately uses the pointer. */ u_box_2d(0, 0, res->width0, res->height0, &box); *buffer = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer); if (!*buffer) { return GL_FALSE; } *width = res->width0; *height = res->height0; *bytesPerValue = util_format_get_blocksize(res->format); pipe->transfer_unmap(pipe, transfer); return GL_TRUE; }
/** * Copy the contents between the attachments. */ static void xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi, enum st_attachment_type src_statt, enum st_attachment_type dst_statt, unsigned x, unsigned y, unsigned width, unsigned height) { struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); struct pipe_resource *src_ptex = xstfb->textures[src_statt]; struct pipe_resource *dst_ptex = xstfb->textures[dst_statt]; struct pipe_box src_box; struct pipe_context *pipe; if (!src_ptex || !dst_ptex) return; pipe = xstfb->display->pipe; if (!pipe) { pipe = xstfb->screen->context_create(xstfb->screen, NULL); if (!pipe) return; xstfb->display->pipe = pipe; } u_box_2d(x, y, width, height, &src_box); if (src_ptex && dst_ptex) pipe->resource_copy_region(pipe, dst_ptex, 0, x, y, 0, src_ptex, 0, &src_box); }
static void fd_resource_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) { struct fd_context *ctx = fd_context(pctx); struct fd_resource *rsc = fd_resource(ptrans->resource); struct fd_transfer *trans = fd_transfer(ptrans); if (trans->staging && !(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) { struct pipe_box box; u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box); fd_resource_flush(trans, &box); } if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { fd_bo_cpu_fini(rsc->bo); if (rsc->stencil) fd_bo_cpu_fini(rsc->stencil->bo); } util_range_add(&rsc->valid_buffer_range, ptrans->box.x, ptrans->box.x + ptrans->box.width); pipe_resource_reference(&ptrans->resource, NULL); util_slab_free(&ctx->transfer_pool, ptrans); free(trans->staging); }
static void r600_color_resolve(struct pipe_context *ctx, const struct pipe_resolve_info *info) { struct r600_context *rctx = (struct r600_context *)ctx; struct pipe_screen *screen = ctx->screen; struct pipe_resource *tmp, templ; struct pipe_box box; unsigned sample_mask = rctx->chip_class == CAYMAN ? ~0 : ((1ull << MAX2(1, info->src.res->nr_samples)) - 1); assert((info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA); if (is_simple_resolve(info)) { r600_blitter_begin(ctx, R600_COLOR_RESOLVE); util_blitter_custom_resolve_color(rctx->blitter, info->dst.res, info->dst.level, info->dst.layer, info->src.res, info->src.layer, sample_mask, rctx->custom_blend_resolve); r600_blitter_end(ctx); return; } /* resolve into a temporary texture, then blit */ templ.target = PIPE_TEXTURE_2D; templ.format = info->src.res->format; templ.width0 = info->src.res->width0; templ.height0 = info->src.res->height0; templ.depth0 = 1; templ.array_size = 1; templ.last_level = 0; templ.nr_samples = 0; templ.usage = PIPE_USAGE_STATIC; templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; templ.flags = 0; tmp = screen->resource_create(screen, &templ); /* XXX use scissor, so that only the needed part of the resource is resolved */ r600_blitter_begin(ctx, R600_COLOR_RESOLVE); util_blitter_custom_resolve_color(rctx->blitter, tmp, 0, 0, info->src.res, info->src.layer, sample_mask, rctx->custom_blend_resolve); r600_blitter_end(ctx); /* this is correct for upside-down blits too */ u_box_2d(info->src.x0, info->src.y0, info->src.x1 - info->src.x0, info->src.y1 - info->src.y0, &box); r600_blitter_begin(ctx, R600_COPY_TEXTURE); util_blitter_copy_texture(rctx->blitter, info->dst.res, info->dst.level, ~0, info->dst.x0, info->dst.y0, info->dst.layer, tmp, 0, 0, &box); r600_blitter_end(ctx); pipe_resource_reference(&tmp, NULL); }
/** Upload the constants. */ static void up_consts(struct pipe_context *pipe) { struct pipe_box box; u_box_2d(0, 0, sizeof(constants), 1, &box); pipe->transfer_inline_write(pipe, constbuf, 0, PIPE_TRANSFER_WRITE, &box, constants, sizeof(constants), sizeof(constants)); }
static void ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen); modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; struct pipe_box src_box; exa_debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n", srcX, srcY, dstX, dstY, width, height); debug_assert(exaGetPixmapDriverPrivate(pDstPixmap) == exa->copy.dst); u_box_2d(srcX, srcY, width, height, &src_box); /* If source and destination overlap, we have to copy to/from a scratch * pixmap. */ if (exa->copy.dst == exa->copy.src && !((dstX + width) < srcX || dstX > (srcX + width) || (dstY + height) < srcY || dstY > (srcY + height))) { struct exa_pixmap_priv *tmp_priv; if (!exa->copy.tmp_pix) { exa->copy.tmp_pix = pScrn->pScreen->CreatePixmap(pScrn->pScreen, pDstPixmap->drawable.width, pDstPixmap->drawable.height, pDstPixmap->drawable.depth, pDstPixmap->drawable.width); exaMoveInPixmap(exa->copy.tmp_pix); } tmp_priv = exaGetPixmapDriverPrivate(exa->copy.tmp_pix); exa->pipe->resource_copy_region( exa->pipe, tmp_priv->tex, 0, srcX, srcY, 0, exa->copy.src->tex, 0, &src_box); exa->pipe->resource_copy_region( exa->pipe, exa->copy.dst->tex, 0, dstX, dstY, 0, tmp_priv->tex, 0, &src_box); } else exa->pipe->resource_copy_region( exa->pipe, exa->copy.dst->tex, 0, dstX, dstY, 0, exa->copy.src->tex, 0, &src_box); }
static void pipe_copy(struct gralloc_drm_drv_t *drv, struct gralloc_drm_bo_t *dst_bo, struct gralloc_drm_bo_t *src_bo, short x1, short y1, short x2, short y2) { struct pipe_manager *pm = (struct pipe_manager *) drv; struct pipe_buffer *dst = (struct pipe_buffer *) dst_bo; struct pipe_buffer *src = (struct pipe_buffer *) src_bo; struct pipe_box src_box; if (dst_bo->handle->width != src_bo->handle->width || dst_bo->handle->height != src_bo->handle->height || dst_bo->handle->stride != src_bo->handle->stride || dst_bo->handle->format != src_bo->handle->format) { LOGE("copy between incompatible buffers"); return; } if (x1 < 0) x1 = 0; if (y1 < 0) y1 = 0; if (x2 > dst_bo->handle->width) x2 = dst_bo->handle->width; if (y2 > dst_bo->handle->height) y2 = dst_bo->handle->height; if (x2 <= x1 || y2 <= y1) return; u_box_2d(x1, y1, x2 - x1, y2 - y1, &src_box); pthread_mutex_lock(&pm->mutex); /* need a context for copying */ if (!pm->context) { pm->context = pm->screen->context_create(pm->screen, NULL); if (!pm->context) { LOGE("failed to create pipe context"); pthread_mutex_unlock(&pm->mutex); return; } } pm->context->resource_copy_region(pm->context, dst->resource, 0, x1, y1, 0, src->resource, 0, &src_box); pm->context->flush(pm->context, NULL); pthread_mutex_unlock(&pm->mutex); }
static void r600_copy_first_sample(struct pipe_context *ctx, const struct pipe_resolve_info *info) { struct r600_context *rctx = (struct r600_context *)ctx; struct r600_texture *rsrc = (struct r600_texture*)info->src.res; struct pipe_surface *dst_view, dst_templ; struct pipe_sampler_view src_templ, *src_view; struct pipe_box box; if (rsrc->is_depth && !rsrc->is_flushing_texture) { if (!r600_init_flushed_depth_texture(ctx, info->src.res, NULL)) return; /* error */ /* Decompress the first sample only. */ r600_blit_decompress_depth(ctx, rsrc, NULL, 0, 0, info->src.layer, info->src.layer, 0, 0); } if (rctx->chip_class != CAYMAN && rsrc->fmask_size && rsrc->cmask_size) { r600_blit_decompress_color(ctx, rsrc, 0, 0, info->src.layer, info->src.layer); } /* this is correct for upside-down blits too */ u_box_2d(info->src.x0, info->src.y0, info->src.x1 - info->src.x0, info->src.y1 - info->src.y0, &box); /* Initialize the surface. */ util_blitter_default_dst_texture(&dst_templ, info->dst.res, info->dst.level, info->dst.layer, &box); dst_view = ctx->create_surface(ctx, info->dst.res, &dst_templ); /* Initialize the sampler view. */ util_blitter_default_src_texture(&src_templ, info->src.res, 0); src_view = ctx->create_sampler_view(ctx, info->src.res, &src_templ); /* Copy the first sample into dst. */ r600_blitter_begin(ctx, R600_COPY_TEXTURE); util_blitter_copy_texture_view(rctx->blitter, dst_view, ~0, info->dst.x0, info->dst.y0, src_view, 0, &box, info->src.res->width0, info->src.res->height0, info->mask); r600_blitter_end(ctx); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); }
/** * Called via glFlush/glFinish. This is where we copy the contents * of the driver's color buffer into the user-specified buffer. */ static boolean osmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, struct st_framebuffer_iface *stfbi, enum st_attachment_type statt) { OSMesaContext osmesa = OSMesaGetCurrentContext(); struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); struct pipe_context *pipe = stctx->pipe; struct pipe_resource *res = osbuffer->textures[statt]; struct pipe_transfer *transfer = NULL; struct pipe_box box; void *map; ubyte *src, *dst; unsigned y, bytes, bpp; int dst_stride; u_box_2d(0, 0, res->width0, res->height0, &box); map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer); /* * Copy the color buffer from the resource to the user's buffer. */ bpp = util_format_get_blocksize(osbuffer->visual.color_format); src = map; dst = osbuffer->map; if (osmesa->user_row_length) dst_stride = bpp * osmesa->user_row_length; else dst_stride = bpp * osbuffer->width; bytes = bpp * res->width0; if (osmesa->y_up) { /* need to flip image upside down */ dst = dst + (res->height0 - 1) * dst_stride; dst_stride = -dst_stride; } for (y = 0; y < res->height0; y++) { memcpy(dst, src, bytes); dst += dst_stride; src += transfer->stride; } pipe->transfer_unmap(pipe, transfer); return TRUE; }
void xa_copy(struct xa_context *ctx, int dx, int dy, int sx, int sy, int width, int height) { struct pipe_box src_box; if (ctx->simple_copy) { u_box_2d(sx, sy, width, height, &src_box); ctx->pipe->resource_copy_region(ctx->pipe, ctx->dst->tex, 0, dx, dy, 0, ctx->src->tex, 0, &src_box); } else renderer_copy(ctx, dx, dy, sx, sy, width, height, (float) width, (float) height); }
XA_EXPORT void xa_copy(struct xa_context *ctx, int dx, int dy, int sx, int sy, int width, int height) { struct pipe_box src_box; xa_scissor_update(ctx, dx, dy, dx + width, dy + height); if (ctx->simple_copy) { u_box_2d(sx, sy, width, height, &src_box); ctx->pipe->resource_copy_region(ctx->pipe, ctx->dst->tex, 0, dx, dy, 0, ctx->src->tex, 0, &src_box); } else renderer_copy(ctx, dx, dy, sx, sy, width, height, (float) ctx->src->tex->width0, (float) ctx->src->tex->height0); }
static void drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, int w, int h) { struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); struct dri_drawable *drawable = dri_drawable(dPriv); struct pipe_resource *ptex; struct pipe_box box; if (!ctx) return; ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; if (ptex) { if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); u_box_2d(x, dPriv->h - y - h, w, h, &box); drisw_present_texture(dPriv, ptex, &box); } }
/** * Try to do a glCopyPixels for simple cases with a blit by calling * pipe->resource_copy_region(). * * We can do this when we're copying color pixels (depth/stencil * eventually) with no pixel zoom, no pixel transfer ops, no * per-fragment ops, the src/dest regions don't overlap and the * src/dest pixel formats are the same. */ static GLboolean blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct gl_pixelstore_attrib pack, unpack; GLint readX, readY, readW, readH; if (type == GL_COLOR && ctx->Pixel.ZoomX == 1.0 && ctx->Pixel.ZoomY == 1.0 && ctx->_ImageTransferState == 0x0 && !ctx->Color.BlendEnabled && !ctx->Color.AlphaEnabled && !ctx->Depth.Test && !ctx->Fog.Enabled && !ctx->Stencil.Enabled && !ctx->FragmentProgram.Enabled && !ctx->VertexProgram.Enabled && !ctx->Shader.CurrentFragmentProgram && st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) && ctx->DrawBuffer->_NumColorDrawBuffers == 1 && !ctx->Query.CondRenderQuery) { struct st_renderbuffer *rbRead, *rbDraw; GLint drawX, drawY; /* * Clip the read region against the src buffer bounds. * We'll still allocate a temporary buffer/texture for the original * src region size but we'll only read the region which is on-screen. * This may mean that we draw garbage pixels into the dest region, but * that's expected. */ readX = srcx; readY = srcy; readW = width; readH = height; pack = ctx->DefaultPacking; if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) return GL_TRUE; /* all done */ /* clip against dest buffer bounds and scissor box */ drawX = dstx + pack.SkipPixels; drawY = dsty + pack.SkipRows; unpack = pack; if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack)) return GL_TRUE; /* all done */ readX = readX - pack.SkipPixels + unpack.SkipPixels; readY = readY - pack.SkipRows + unpack.SkipRows; rbRead = st_get_color_read_renderbuffer(ctx); rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); if ((rbRead != rbDraw || !regions_overlap(readX, readY, drawX, drawY, readW, readH)) && rbRead->Base.Format == rbDraw->Base.Format) { struct pipe_box srcBox; /* flip src/dst position if needed */ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { /* both buffers will have the same orientation */ readY = ctx->ReadBuffer->Height - readY - readH; drawY = ctx->DrawBuffer->Height - drawY - readH; } u_box_2d(readX, readY, readW, readH, &srcBox); pipe->resource_copy_region(pipe, rbDraw->texture, rbDraw->rtt_level, drawX, drawY, 0, rbRead->texture, rbRead->rtt_level, &srcBox); return GL_TRUE; } } return GL_FALSE; }
/** * Called via glFlush/glFinish. This is where we copy the contents * of the driver's color buffer into the user-specified buffer. */ static boolean osmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, struct st_framebuffer_iface *stfbi, enum st_attachment_type statt) { OSMesaContext osmesa = OSMesaGetCurrentContext(); struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); struct pipe_context *pipe = stctx->pipe; struct pipe_resource *res = osbuffer->textures[statt]; struct pipe_transfer *transfer = NULL; struct pipe_box box; void *map; ubyte *src, *dst; unsigned y, bytes, bpp; int dst_stride; if (osmesa->pp) { struct pipe_resource *zsbuf = NULL; unsigned i; /* Find the z/stencil buffer if there is one */ for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) { struct pipe_resource *res = osbuffer->textures[i]; if (res) { const struct util_format_description *desc = util_format_description(res->format); if (util_format_has_depth(desc)) { zsbuf = res; break; } } } /* run the postprocess stage(s) */ pp_run(osmesa->pp, res, res, zsbuf); } u_box_2d(0, 0, res->width0, res->height0, &box); map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer); /* * Copy the color buffer from the resource to the user's buffer. */ bpp = util_format_get_blocksize(osbuffer->visual.color_format); src = map; dst = osbuffer->map; if (osmesa->user_row_length) dst_stride = bpp * osmesa->user_row_length; else dst_stride = bpp * osbuffer->width; bytes = bpp * res->width0; if (osmesa->y_up) { /* need to flip image upside down */ dst = dst + (res->height0 - 1) * dst_stride; dst_stride = -dst_stride; } for (y = 0; y < res->height0; y++) { memcpy(dst, src, bytes); dst += dst_stride; src += transfer->stride; } pipe->transfer_unmap(pipe, transfer); return TRUE; }
/** The init function of the MLAA filter. */ static bool pp_jimenezmlaa_init_run(struct pp_queue_t *ppq, unsigned int n, unsigned int val, bool iscolor) { struct pipe_box box; struct pipe_resource res; char *tmp_text = NULL; tmp_text = CALLOC(sizeof(blend2fs_1) + sizeof(blend2fs_2) + IMM_SPACE, sizeof(char)); if (tmp_text == NULL) { pp_debug("Failed to allocate shader space\n"); return FALSE; } ppq->constbuf = pipe_buffer_create(ppq->p->screen, PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_DEFAULT, sizeof(constants)); if (ppq->constbuf == NULL) { pp_debug("Failed to allocate constant buffer\n"); goto fail; } pp_debug("mlaa: using %u max search steps\n", val); util_sprintf(tmp_text, "%s" "IMM FLT32 { %.8f, 0.0000, 0.0000, 0.0000}\n" "%s\n", blend2fs_1, (float) val, blend2fs_2); memset(&res, 0, sizeof(res)); res.target = PIPE_TEXTURE_2D; res.format = PIPE_FORMAT_R8G8_UNORM; res.width0 = res.height0 = 165; res.bind = PIPE_BIND_SAMPLER_VIEW; res.usage = PIPE_USAGE_DEFAULT; res.depth0 = res.array_size = res.nr_samples = 1; if (!ppq->p->screen->is_format_supported(ppq->p->screen, res.format, res.target, 1, res.bind)) pp_debug("Areamap format not supported\n"); ppq->areamaptex = ppq->p->screen->resource_create(ppq->p->screen, &res); if (ppq->areamaptex == NULL) { pp_debug("Failed to allocate area map texture\n"); goto fail; } u_box_2d(0, 0, 165, 165, &box); ppq->p->pipe->transfer_inline_write(ppq->p->pipe, ppq->areamaptex, 0, PIPE_TRANSFER_WRITE, &box, areamap, 165 * 2, sizeof(areamap)); ppq->shaders[n][1] = pp_tgsi_to_state(ppq->p->pipe, offsetvs, true, "offsetvs"); if (iscolor) ppq->shaders[n][2] = pp_tgsi_to_state(ppq->p->pipe, color1fs, false, "color1fs"); else ppq->shaders[n][2] = pp_tgsi_to_state(ppq->p->pipe, depth1fs, false, "depth1fs"); ppq->shaders[n][3] = pp_tgsi_to_state(ppq->p->pipe, tmp_text, false, "blend2fs"); ppq->shaders[n][4] = pp_tgsi_to_state(ppq->p->pipe, neigh3fs, false, "neigh3fs"); FREE(tmp_text); return TRUE; fail: FREE(tmp_text); /* * Call the common free function for destruction of partially initialized * resources. */ pp_jimenezmlaa_free(ppq, n); return FALSE; }
static void test_sync_file_fences(struct pipe_context *ctx) { struct pipe_screen *screen = ctx->screen; bool pass = true; enum pipe_fd_type fd_type = PIPE_FD_TYPE_NATIVE_SYNC; if (!screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD)) return; struct cso_context *cso = cso_create_context(ctx, 0); struct pipe_resource *buf = pipe_buffer_create(screen, 0, PIPE_USAGE_DEFAULT, 1024 * 1024); struct pipe_resource *tex = util_create_texture2d(screen, 4096, 1024, PIPE_FORMAT_R8_UNORM, 0); struct pipe_fence_handle *buf_fence = NULL, *tex_fence = NULL; /* Run 2 clears, get fencess. */ uint32_t value = 0; ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value)); ctx->flush(ctx, &buf_fence, PIPE_FLUSH_FENCE_FD); struct pipe_box box; u_box_2d(0, 0, tex->width0, tex->height0, &box); ctx->clear_texture(ctx, tex, 0, &box, &value); ctx->flush(ctx, &tex_fence, PIPE_FLUSH_FENCE_FD); pass = pass && buf_fence && tex_fence; /* Export fences. */ int buf_fd = screen->fence_get_fd(screen, buf_fence); int tex_fd = screen->fence_get_fd(screen, tex_fence); pass = pass && buf_fd >= 0 && tex_fd >= 0; /* Merge fences. */ int merged_fd = sync_merge("test", buf_fd, tex_fd); pass = pass && merged_fd >= 0; /* (Re)import all fences. */ struct pipe_fence_handle *re_buf_fence = NULL, *re_tex_fence = NULL; struct pipe_fence_handle *merged_fence = NULL; ctx->create_fence_fd(ctx, &re_buf_fence, buf_fd, fd_type); ctx->create_fence_fd(ctx, &re_tex_fence, tex_fd, fd_type); ctx->create_fence_fd(ctx, &merged_fence, merged_fd, fd_type); pass = pass && re_buf_fence && re_tex_fence && merged_fence; /* Run another clear after waiting for everything. */ struct pipe_fence_handle *final_fence = NULL; ctx->fence_server_sync(ctx, merged_fence); value = 0xff; ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value)); ctx->flush(ctx, &final_fence, PIPE_FLUSH_FENCE_FD); pass = pass && final_fence; /* Wait for the last fence. */ int final_fd = screen->fence_get_fd(screen, final_fence); pass = pass && final_fd >= 0; pass = pass && sync_wait(final_fd, -1) == 0; /* Check that all fences are signalled. */ pass = pass && sync_wait(buf_fd, 0) == 0; pass = pass && sync_wait(tex_fd, 0) == 0; pass = pass && sync_wait(merged_fd, 0) == 0; pass = pass && screen->fence_finish(screen, NULL, buf_fence, 0); pass = pass && screen->fence_finish(screen, NULL, tex_fence, 0); pass = pass && screen->fence_finish(screen, NULL, re_buf_fence, 0); pass = pass && screen->fence_finish(screen, NULL, re_tex_fence, 0); pass = pass && screen->fence_finish(screen, NULL, merged_fence, 0); pass = pass && screen->fence_finish(screen, NULL, final_fence, 0); /* Cleanup. */ #ifndef PIPE_OS_WINDOWS if (buf_fd >= 0) close(buf_fd); if (tex_fd >= 0) close(tex_fd); if (merged_fd >= 0) close(merged_fd); if (final_fd >= 0) close(final_fd); #endif screen->fence_reference(screen, &buf_fence, NULL); screen->fence_reference(screen, &tex_fence, NULL); screen->fence_reference(screen, &re_buf_fence, NULL); screen->fence_reference(screen, &re_tex_fence, NULL); screen->fence_reference(screen, &merged_fence, NULL); screen->fence_reference(screen, &final_fence, NULL); cso_destroy_context(cso); pipe_resource_reference(&buf, NULL); pipe_resource_reference(&tex, NULL); util_report_result(pass); }
/* In the case of transfer_map of a multi-sample resource, call back into * pctx->transfer_map() to map the staging resource, to handle cases of * MSAA + separate_z32s8 or fake_rgtc */ static void * transfer_map_msaa(struct pipe_context *pctx, struct pipe_resource *prsc, unsigned level, unsigned usage, const struct pipe_box *box, struct pipe_transfer **pptrans) { struct pipe_screen *pscreen = pctx->screen; struct u_transfer *trans = calloc(1, sizeof(*trans)); if (!trans) return NULL; struct pipe_transfer *ptrans = &trans->base; pipe_resource_reference(&ptrans->resource, prsc); ptrans->level = level; ptrans->usage = usage; ptrans->box = *box; struct pipe_resource tmpl = { .target = prsc->target, .format = prsc->format, .width0 = box->width, .height0 = box->height, .depth0 = 1, .array_size = 1, }; trans->ss = pscreen->resource_create(pscreen, &tmpl); if (!trans->ss) { free(trans); return NULL; } if (needs_pack(usage)) { struct pipe_blit_info blit; memset(&blit, 0, sizeof(blit)); blit.src.resource = ptrans->resource; blit.src.format = ptrans->resource->format; blit.src.level = ptrans->level; blit.src.box = *box; blit.dst.resource = trans->ss; blit.dst.format = trans->ss->format; blit.dst.box.width = box->width; blit.dst.box.height = box->height; blit.dst.box.depth = 1; blit.mask = util_format_get_mask(prsc->format); blit.filter = PIPE_TEX_FILTER_NEAREST; pctx->blit(pctx, &blit); } struct pipe_box map_box = *box; map_box.x = 0; map_box.y = 0; void *ss_map = pctx->transfer_map(pctx, trans->ss, 0, usage, &map_box, &trans->trans); if (!ss_map) { free(trans); return NULL; } ptrans->stride = trans->trans->stride; *pptrans = ptrans; return ss_map; } void * u_transfer_helper_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, unsigned level, unsigned usage, const struct pipe_box *box, struct pipe_transfer **pptrans) { struct u_transfer_helper *helper = pctx->screen->transfer_helper; struct u_transfer *trans; struct pipe_transfer *ptrans; enum pipe_format format = prsc->format; unsigned width = box->width; unsigned height = box->height; if (!handle_transfer(prsc)) return helper->vtbl->transfer_map(pctx, prsc, level, usage, box, pptrans); if (helper->msaa_map && (prsc->nr_samples > 1)) return transfer_map_msaa(pctx, prsc, level, usage, box, pptrans); debug_assert(box->depth == 1); trans = calloc(1, sizeof(*trans)); if (!trans) return NULL; ptrans = &trans->base; pipe_resource_reference(&ptrans->resource, prsc); ptrans->level = level; ptrans->usage = usage; ptrans->box = *box; ptrans->stride = util_format_get_stride(format, box->width); ptrans->layer_stride = ptrans->stride * box->height; trans->staging = malloc(ptrans->layer_stride); if (!trans->staging) goto fail; trans->ptr = helper->vtbl->transfer_map(pctx, prsc, level, usage, box, &trans->trans); if (!trans->ptr) goto fail; if (prsc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) { struct pipe_resource *stencil = helper->vtbl->get_stencil(prsc); trans->ptr2 = helper->vtbl->transfer_map(pctx, stencil, level, usage, box, &trans->trans2); if (needs_pack(usage)) { util_format_z32_float_s8x24_uint_pack_z_float(trans->staging, ptrans->stride, trans->ptr, trans->trans->stride, width, height); util_format_z32_float_s8x24_uint_pack_s_8uint(trans->staging, ptrans->stride, trans->ptr2, trans->trans2->stride, width, height); } } else if (needs_pack(usage) && util_format_description(prsc->format)->layout == UTIL_FORMAT_LAYOUT_RGTC) { switch (prsc->format) { case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_RGTC1_SNORM: case PIPE_FORMAT_LATC1_UNORM: case PIPE_FORMAT_LATC1_SNORM: util_format_rgtc1_unorm_pack_rgba_8unorm(trans->staging, ptrans->stride, trans->ptr, trans->trans->stride, width, height); break; case PIPE_FORMAT_RGTC2_UNORM: case PIPE_FORMAT_RGTC2_SNORM: case PIPE_FORMAT_LATC2_UNORM: case PIPE_FORMAT_LATC2_SNORM: util_format_rgtc2_unorm_pack_rgba_8unorm(trans->staging, ptrans->stride, trans->ptr, trans->trans->stride, width, height); break; default: assert(!"Unexpected format"); break; } } else { unreachable("bleh"); } *pptrans = ptrans; return trans->staging; fail: if (trans->trans) helper->vtbl->transfer_unmap(pctx, trans->trans); if (trans->trans2) helper->vtbl->transfer_unmap(pctx, trans->trans2); pipe_resource_reference(&ptrans->resource, NULL); free(trans->staging); free(trans); return NULL; } static void flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, const struct pipe_box *box) { struct u_transfer_helper *helper = pctx->screen->transfer_helper; struct u_transfer *trans = u_transfer(ptrans); enum pipe_format iformat, format = ptrans->resource->format; unsigned width = box->width; unsigned height = box->height; void *src, *dst; if (!(ptrans->usage & PIPE_TRANSFER_WRITE)) return; if (trans->ss) { struct pipe_blit_info blit; memset(&blit, 0, sizeof(blit)); blit.src.resource = trans->ss; blit.src.format = trans->ss->format; blit.src.box = *box; blit.dst.resource = ptrans->resource; blit.dst.format = ptrans->resource->format; blit.dst.level = ptrans->level; u_box_2d(ptrans->box.x + box->x, ptrans->box.y + box->y, box->width, box->height, &blit.dst.box); blit.mask = util_format_get_mask(ptrans->resource->format); blit.filter = PIPE_TEX_FILTER_NEAREST; pctx->blit(pctx, &blit); return; } iformat = helper->vtbl->get_internal_format(ptrans->resource); src = (uint8_t *)trans->staging + (box->y * ptrans->stride) + (box->x * util_format_get_blocksize(format)); dst = (uint8_t *)trans->ptr + (box->y * trans->trans->stride) + (box->x * util_format_get_blocksize(iformat)); switch (format) { case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: util_format_z32_float_s8x24_uint_unpack_z_float(dst, trans->trans->stride, src, ptrans->stride, width, height); /* fallthru */ case PIPE_FORMAT_X32_S8X24_UINT: dst = (uint8_t *)trans->ptr2 + (box->y * trans->trans2->stride) + (box->x * util_format_get_blocksize(PIPE_FORMAT_S8_UINT)); util_format_z32_float_s8x24_uint_unpack_s_8uint(dst, trans->trans2->stride, src, ptrans->stride, width, height); break; case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_RGTC1_SNORM: case PIPE_FORMAT_LATC1_UNORM: case PIPE_FORMAT_LATC1_SNORM: util_format_rgtc1_unorm_unpack_rgba_8unorm(dst, trans->trans->stride, src, ptrans->stride, width, height); break; case PIPE_FORMAT_RGTC2_UNORM: case PIPE_FORMAT_RGTC2_SNORM: case PIPE_FORMAT_LATC2_UNORM: case PIPE_FORMAT_LATC2_SNORM: util_format_rgtc2_unorm_unpack_rgba_8unorm(dst, trans->trans->stride, src, ptrans->stride, width, height); break; default: assert(!"Unexpected staging transfer type"); break; } } void u_transfer_helper_transfer_flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, const struct pipe_box *box) { struct u_transfer_helper *helper = pctx->screen->transfer_helper; if (handle_transfer(ptrans->resource)) { struct u_transfer *trans = u_transfer(ptrans); flush_region(pctx, ptrans, box); /* handle MSAA case, since there could be multiple levels of * wrapped transfer, call pctx->transfer_flush_region() * instead of helper->vtbl->transfer_flush_region() */ if (trans->ss) { pctx->transfer_flush_region(pctx, trans->trans, box); return; } helper->vtbl->transfer_flush_region(pctx, trans->trans, box); if (trans->trans2) helper->vtbl->transfer_flush_region(pctx, trans->trans2, box); } else { helper->vtbl->transfer_flush_region(pctx, ptrans, box); } } void u_transfer_helper_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) { struct u_transfer_helper *helper = pctx->screen->transfer_helper; if (handle_transfer(ptrans->resource)) { struct u_transfer *trans = u_transfer(ptrans); if (!(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) { struct pipe_box box; u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box); flush_region(pctx, ptrans, &box); } /* in MSAA case, there could be multiple levels of wrapping * so don't call helper->vtbl->transfer_unmap() directly */ if (trans->ss) { pctx->transfer_unmap(pctx, trans->trans); pipe_resource_reference(&trans->ss, NULL); } else { helper->vtbl->transfer_unmap(pctx, trans->trans); if (trans->trans2) helper->vtbl->transfer_unmap(pctx, trans->trans2); } free(trans); } else { helper->vtbl->transfer_unmap(pctx, ptrans); } } struct u_transfer_helper * u_transfer_helper_create(const struct u_transfer_vtbl *vtbl, bool separate_z32s8, bool fake_rgtc, bool msaa_map) { struct u_transfer_helper *helper = calloc(1, sizeof(*helper)); helper->vtbl = vtbl; helper->separate_z32s8 = separate_z32s8; helper->fake_rgtc = fake_rgtc; helper->msaa_map = msaa_map; return helper; } void u_transfer_helper_destroy(struct u_transfer_helper *helper) { free(helper); }
static void init_tex( void ) { struct pipe_sampler_view sv_template; struct pipe_sampler_state sampler_desc; struct pipe_resource templat; struct pipe_box box; ubyte tex2d[SIZE][SIZE][4]; int s, t; #if (SIZE != 2) for (s = 0; s < SIZE; s++) { for (t = 0; t < SIZE; t++) { if (0) { int x = (s ^ t) & 1; tex2d[t][s][0] = (x) ? 0 : 63; tex2d[t][s][1] = (x) ? 0 : 128; tex2d[t][s][2] = 0; tex2d[t][s][3] = 0xff; } else { int x = ((s ^ t) >> 2) & 1; tex2d[t][s][0] = s*255/(SIZE-1); tex2d[t][s][1] = t*255/(SIZE-1); tex2d[t][s][2] = (x) ? 0 : 128; tex2d[t][s][3] = 0xff; } } } #else tex2d[0][0][0] = 0; tex2d[0][0][1] = 255; tex2d[0][0][2] = 255; tex2d[0][0][3] = 0; tex2d[0][1][0] = 0; tex2d[0][1][1] = 0; tex2d[0][1][2] = 255; tex2d[0][1][3] = 255; tex2d[1][0][0] = 255; tex2d[1][0][1] = 255; tex2d[1][0][2] = 0; tex2d[1][0][3] = 255; tex2d[1][1][0] = 255; tex2d[1][1][1] = 0; tex2d[1][1][2] = 0; tex2d[1][1][3] = 255; #endif templat.target = PIPE_TEXTURE_2D; templat.format = PIPE_FORMAT_B8G8R8A8_UNORM; templat.width0 = SIZE; templat.height0 = SIZE; templat.depth0 = 1; templat.array_size = 1; templat.last_level = 0; templat.nr_samples = 1; templat.bind = PIPE_BIND_SAMPLER_VIEW; samptex = screen->resource_create(screen, &templat); if (samptex == NULL) exit(4); u_box_2d(0,0,SIZE,SIZE, &box); ctx->transfer_inline_write(ctx, samptex, 0, PIPE_TRANSFER_WRITE, &box, tex2d, sizeof tex2d[0], sizeof tex2d); /* Possibly read back & compare against original data: */ if (0) { struct pipe_transfer *t; uint32_t *ptr; t = pipe_get_transfer(ctx, samptex, 0, 0, /* level, layer */ PIPE_TRANSFER_READ, 0, 0, SIZE, SIZE); /* x, y, width, height */ ptr = ctx->transfer_map(ctx, t); if (memcmp(ptr, tex2d, sizeof tex2d) != 0) { assert(0); exit(9); } ctx->transfer_unmap(ctx, t); ctx->transfer_destroy(ctx, t); } memset(&sv_template, 0, sizeof sv_template); sv_template.format = samptex->format; sv_template.texture = samptex; sv_template.swizzle_r = 0; sv_template.swizzle_g = 1; sv_template.swizzle_b = 2; sv_template.swizzle_a = 3; sv = ctx->create_sampler_view(ctx, samptex, &sv_template); if (sv == NULL) exit(5); ctx->set_fragment_sampler_views(ctx, 1, &sv); memset(&sampler_desc, 0, sizeof sampler_desc); sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT; sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT; sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT; sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST; sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST; sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE; sampler_desc.compare_func = 0; sampler_desc.normalized_coords = 1; sampler_desc.max_anisotropy = 0; sampler = ctx->create_sampler_state(ctx, &sampler_desc); if (sampler == NULL) exit(6); ctx->bind_fragment_sampler_states(ctx, 1, &sampler); }
static void st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *rbRead; void *driver_vp, *driver_fp; struct pipe_resource *pt; struct pipe_sampler_view *sv[2]; int num_sampler_view = 1; GLfloat *color; enum pipe_format srcFormat, texFormat; GLboolean invertTex = GL_FALSE; GLint readX, readY, readW, readH; GLuint sample_count; struct gl_pixelstore_attrib pack = ctx->DefaultPacking; struct st_fp_variant *fpv; st_validate_state(st); if (type == GL_STENCIL) { /* can't use texturing to do stencil */ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); return; } if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type)) return; /* * The subsequent code implements glCopyPixels by copying the source * pixels into a temporary texture that's then applied to a textured quad. * When we draw the textured quad, all the usual per-fragment operations * are handled. */ /* * Get vertex/fragment shaders */ if (type == GL_COLOR) { rbRead = st_get_color_read_renderbuffer(ctx); color = NULL; fpv = get_color_fp_variant(st); driver_fp = fpv->driver_shader; driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; num_sampler_view++; } } else { assert(type == GL_DEPTH); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE); driver_fp = fpv->driver_shader; driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); } /* update fragment program constants */ st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); if (rbRead->Base.Wrapped) rbRead = st_renderbuffer(rbRead->Base.Wrapped); sample_count = rbRead->texture->nr_samples; /* I believe this would be legal, presumably would need to do a resolve for color, and for depth/stencil spec says to just use one of the depth/stencil samples per pixel? Need some transfer clarifications. */ assert(sample_count < 2); srcFormat = rbRead->texture->format; if (screen->is_format_supported(screen, srcFormat, st->internal_target, sample_count, PIPE_BIND_SAMPLER_VIEW)) { texFormat = srcFormat; } else { /* srcFormat can't be used as a texture format */ if (type == GL_DEPTH) { texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, GL_NONE, GL_NONE, st->internal_target, sample_count, PIPE_BIND_DEPTH_STENCIL); assert(texFormat != PIPE_FORMAT_NONE); } else { /* default color format */ texFormat = st_choose_format(screen, GL_RGBA, GL_NONE, GL_NONE, st->internal_target, sample_count, PIPE_BIND_SAMPLER_VIEW); assert(texFormat != PIPE_FORMAT_NONE); } } /* Invert src region if needed */ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { srcy = ctx->ReadBuffer->Height - srcy - height; invertTex = !invertTex; } /* Clip the read region against the src buffer bounds. * We'll still allocate a temporary buffer/texture for the original * src region size but we'll only read the region which is on-screen. * This may mean that we draw garbage pixels into the dest region, but * that's expected. */ readX = srcx; readY = srcy; readW = width; readH = height; _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack); readW = MAX2(0, readW); readH = MAX2(0, readH); /* alloc temporary texture */ pt = alloc_texture(st, width, height, texFormat); if (!pt) return; sv[0] = st_create_texture_sampler_view(st->pipe, pt); if (!sv[0]) { pipe_resource_reference(&pt, NULL); return; } /* Make temporary texture which is a copy of the src region. */ if (srcFormat == texFormat) { struct pipe_box src_box; u_box_2d(readX, readY, readW, readH, &src_box); /* copy source framebuffer surface into mipmap/texture */ pipe->resource_copy_region(pipe, pt, /* dest tex */ 0, /* dest lvl */ pack.SkipPixels, pack.SkipRows, 0, /* dest pos */ rbRead->texture, /* src tex */ rbRead->rtt_level, /* src lvl */ &src_box); } else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = pipe_get_transfer(st->pipe, rbRead->texture, rbRead->rtt_level, rbRead->rtt_face + rbRead->rtt_slice, PIPE_TRANSFER_READ, readX, readY, readW, readH); struct pipe_transfer *ptTex; enum pipe_transfer_usage transfer_usage; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; else transfer_usage = PIPE_TRANSFER_WRITE; ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage, 0, 0, width, height); /* copy image from ptRead surface to ptTex surface */ if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); enum pipe_format readFormat, drawFormat; readFormat = util_format_linear(rbRead->texture->format); drawFormat = util_format_linear(pt->format); pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH, readFormat, buf); pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows, readW, readH, drawFormat, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf); pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, readW, readH, buf); free(buf); } pipe->transfer_destroy(pipe, ptRead); pipe->transfer_destroy(pipe, ptTex); } /* OK, the texture 'pt' contains the src image/pixels. Now draw a * textured quad with that texture. */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, sv, num_sampler_view, driver_vp, driver_fp, color, invertTex, GL_FALSE, GL_FALSE); pipe_resource_reference(&pt, NULL); pipe_sampler_view_reference(&sv[0], NULL); }