static Bool ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, int src_pitch) { ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); struct pipe_transfer *transfer; void *map; if (!priv || !priv->tex) return FALSE; map = pipe_transfer_map(exa->pipe, priv->tex, 0, 0, PIPE_TRANSFER_WRITE, x, y, w, h, &transfer); if (!map) return FALSE; exa_debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n", x, y, w, h, src_pitch); util_copy_rect(map, priv->tex->format, transfer->stride, 0, 0, w, h, (unsigned char*)src, src_pitch, 0, 0); exa->pipe->transfer_unmap(exa->pipe, transfer); return TRUE; }
static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx, const VGuint *color_data, const VGint color_data_len) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_resource *tex = 0; struct pipe_resource templ; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_1D; templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; templ.last_level = 0; templ.width0 = color_data_len; templ.height0 = 1; templ.depth0 = 1; templ.array_size = 1; templ.bind = PIPE_BIND_SAMPLER_VIEW; tex = screen->resource_create(screen, &templ); { /* upload color_data */ struct pipe_transfer *transfer; void *map = pipe_transfer_map(pipe, tex, 0, 0, PIPE_TRANSFER_READ_WRITE , 0, 0, tex->width0, tex->height0, &transfer); memcpy(map, color_data, sizeof(VGint)*color_data_len); pipe->transfer_unmap(pipe, transfer); } return tex; }
/** * Fallback for pipe->clear_render_target() function. * XXX this looks too hackish to be really useful. * cpp > 4 looks like a gross hack at best... * Plus can't use these transfer fallbacks when clearing * multisampled surfaces for instance. */ void util_clear_render_target(struct pipe_context *pipe, struct pipe_surface *dst, const union pipe_color_union *color, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { struct pipe_transfer *dst_trans; void *dst_map; union util_color uc; assert(dst->texture); if (!dst->texture) return; /* XXX: should handle multiple layers */ dst_map = pipe_transfer_map(pipe, dst->texture, dst->u.tex.level, dst->u.tex.first_layer, PIPE_TRANSFER_WRITE, dstx, dsty, width, height, &dst_trans); assert(dst_map); if (dst_map) { assert(dst_trans->stride > 0); util_pack_color(color->f, dst->texture->format, &uc); util_fill_rect(dst_map, dst->texture->format, dst_trans->stride, 0, 0, width, height, &uc); pipe->transfer_unmap(pipe, dst_trans); } }
/** * Specify the surface to cache. */ void sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, struct pipe_surface *ps) { struct pipe_context *pipe = tc->pipe; if (tc->transfer_map) { if (ps == tc->surface) return; pipe->transfer_unmap(pipe, tc->transfer); tc->transfer = NULL; tc->transfer_map = NULL; } tc->surface = ps; if (ps) { if (ps->texture->target != PIPE_BUFFER) { tc->transfer_map = pipe_transfer_map(pipe, ps->texture, ps->u.tex.level, ps->u.tex.first_layer, PIPE_TRANSFER_READ_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED, 0, 0, ps->width, ps->height, &tc->transfer); } else { /* can't render to buffers */ assert(0); } tc->depth_stencil = util_format_is_depth_or_stencil(ps->format); } }
void * xa_surface_map(struct xa_context *ctx, struct xa_surface *srf, unsigned int usage) { void *map; unsigned int transfer_direction = 0; struct pipe_context *pipe = ctx->pipe; if (srf->transfer) return NULL; if (usage & XA_MAP_READ) transfer_direction = PIPE_TRANSFER_READ; if (usage & XA_MAP_WRITE) transfer_direction = PIPE_TRANSFER_WRITE; if (!transfer_direction) return NULL; srf->transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, transfer_direction, 0, 0, srf->tex->width0, srf->tex->height0); if (!srf->transfer) return NULL; map = pipe_transfer_map(pipe, srf->transfer); if (!map) pipe->transfer_destroy(pipe, srf->transfer); srf->mapping_pipe = pipe; return map; }
static Bool ExaPrepareAccess(PixmapPtr pPix, int index) { ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; struct exa_pixmap_priv *priv; priv = exaGetPixmapDriverPrivate(pPix); if (!priv) return FALSE; if (!priv->tex) return FALSE; exa_debug_printf("ExaPrepareAccess %d\n", index); if (priv->map_count == 0) { assert(pPix->drawable.width <= priv->tex->width0); assert(pPix->drawable.height <= priv->tex->height0); pPix->devPrivate.ptr = pipe_transfer_map(exa->pipe, priv->tex, 0, 0, #ifdef EXA_MIXED_PIXMAPS PIPE_TRANSFER_MAP_DIRECTLY | #endif PIPE_TRANSFER_READ_WRITE, 0, 0, pPix->drawable.width, pPix->drawable.height, &priv->map_transfer); if (!pPix->devPrivate.ptr) #ifdef EXA_MIXED_PIXMAPS return FALSE; #else FatalError("failed to create transfer\n"); #endif pPix->devKind = priv->map_transfer->stride; } priv->map_count++; exa_debug_printf("ExaPrepareAccess %d prepared\n", index); return TRUE; }
/** * Probe and test if the rectangle contains the expected color. * * If "num_expected_colors" > 1, at least one expected color must match * the probed color. "expected" should be an array of 4*num_expected_colors * floats. */ static bool util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex, unsigned offx, unsigned offy, unsigned w, unsigned h, const float *expected, unsigned num_expected_colors) { struct pipe_transfer *transfer; void *map; float *pixels = malloc(w * h * 4 * sizeof(float)); int x,y,e,c; bool pass = true; map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ, offx, offy, w, h, &transfer); pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels); pipe_transfer_unmap(ctx, transfer); for (e = 0; e < num_expected_colors; e++) { for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { float *probe = &pixels[(y*w + x)*4]; for (c = 0; c < 4; c++) { if (fabs(probe[c] - expected[e*4+c]) >= TOLERANCE) { if (e < num_expected_colors-1) goto next_color; /* test the next expected color */ printf("Probe color at (%i,%i), ", offx+x, offy+y); printf("Expected: %.3f, %.3f, %.3f, %.3f, ", expected[e*4], expected[e*4+1], expected[e*4+2], expected[e*4+3]); printf("Got: %.3f, %.3f, %.3f, %.3f\n", probe[0], probe[1], probe[2], probe[2]); pass = false; goto done; } } } } break; /* this color was successful */ next_color:; } done: free(pixels); return pass; }
int xa_surface_dma(struct xa_context *ctx, struct xa_surface *srf, void *data, unsigned int pitch, int to_surface, struct xa_box *boxes, unsigned int num_boxes) { struct pipe_transfer *transfer; void *map; int w, h, i; enum pipe_transfer_usage transfer_direction; struct pipe_context *pipe = ctx->pipe; transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE : PIPE_TRANSFER_READ); for (i = 0; i < num_boxes; ++i, ++boxes) { w = boxes->x2 - boxes->x1; h = boxes->y2 - boxes->y1; transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, transfer_direction, boxes->x1, boxes->y1, w, h); if (!transfer) return -XA_ERR_NORES; map = pipe_transfer_map(ctx->pipe, transfer); if (!map) goto out_no_map; if (to_surface) { util_copy_rect(map, srf->tex->format, transfer->stride, 0, 0, w, h, data, pitch, boxes->x1, boxes->y1); } else { util_copy_rect(data, srf->tex->format, pitch, boxes->x1, boxes->y1, w, h, map, transfer->stride, 0, 0); } pipe->transfer_unmap(pipe, transfer); pipe->transfer_destroy(pipe, transfer); if (to_surface) pipe->flush(pipe, &ctx->last_fence); } return XA_ERR_NONE; out_no_map: pipe->transfer_destroy(pipe, transfer); return -XA_ERR_NORES; }
/** * Create a texture which represents a bitmap image. */ static struct pipe_resource * make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_transfer *transfer; ubyte *dest; struct pipe_resource *pt; /* PBO source... */ bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap); if (!bitmap) { return NULL; } /** * Create texture to hold bitmap pattern. */ pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format, 0, width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); if (!pt) { _mesa_unmap_pbo_source(ctx, unpack); return NULL; } transfer = pipe_get_transfer(st->pipe, pt, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, width, height); dest = pipe_transfer_map(pipe, transfer); /* Put image into texture transfer */ memset(dest, 0xff, height * transfer->stride); unpack_bitmap(st, 0, 0, width, height, unpack, bitmap, dest, transfer->stride); _mesa_unmap_pbo_source(ctx, unpack); /* Release transfer */ pipe_transfer_unmap(pipe, transfer); pipe->transfer_destroy(pipe, transfer); return pt; }
void debug_dump_surface_bmp(struct pipe_context *pipe, const char *filename, struct pipe_surface *surface) { struct pipe_transfer *transfer; struct pipe_resource *texture = surface->texture; void *ptr; ptr = pipe_transfer_map(pipe, texture, surface->u.tex.level, surface->u.tex.first_layer, PIPE_TRANSFER_READ, 0, 0, surface->width, surface->height, &transfer); debug_dump_transfer_bmp(pipe, filename, transfer, ptr); pipe->transfer_unmap(pipe, transfer); }
static int pipe_map(struct gralloc_drm_drv_t *drv, struct gralloc_drm_bo_t *bo, int x, int y, int w, int h, int enable_write, void **addr) { struct pipe_manager *pm = (struct pipe_manager *) drv; struct pipe_buffer *buf = (struct pipe_buffer *) bo; int err = 0; pthread_mutex_lock(&pm->mutex); /* need a context to get transfer */ if (!pm->context) { pm->context = pm->screen->context_create(pm->screen, NULL); if (!pm->context) { LOGE("failed to create pipe context"); err = -ENOMEM; } } if (!err) { enum pipe_transfer_usage usage; usage = PIPE_TRANSFER_READ; if (enable_write) usage |= PIPE_TRANSFER_WRITE; assert(!buf->transfer); /* * ignore x, y, w and h so that returned addr points at the * start of the buffer */ buf->transfer = pipe_get_transfer(pm->context, buf->resource, 0, 0, usage, 0, 0, buf->resource->width0, buf->resource->height0); if (buf->transfer) *addr = pipe_transfer_map(pm->context, buf->transfer); else err = -ENOMEM; } pthread_mutex_unlock(&pm->mutex); return err; }
/** * Map a texture image and return the address for a particular 2D face/slice/ * layer. The stImage indicates the cube face and mipmap level. The slice * of the 3D texture is passed in 'zoffset'. * \param usage one of the PIPE_TRANSFER_x values * \param x, y, w, h the region of interest of the 2D image. * \return address of mapping or NULL if any error */ GLubyte * st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, GLuint zoffset, enum pipe_transfer_usage usage, GLuint x, GLuint y, GLuint w, GLuint h) { struct pipe_context *pipe = st->pipe; struct pipe_resource *pt = stImage->pt; DBG("%s \n", __FUNCTION__); stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->face, stImage->level, zoffset, usage, x, y, w, h); if (stImage->transfer) return pipe_transfer_map(pipe, stImage->transfer); else return NULL; }
/** * Create gallium pipe_transfer object for the bitmap cache. */ static void create_cache_trans(struct st_context *st) { struct pipe_context *pipe = st->pipe; struct bitmap_cache *cache = st->bitmap.cache; if (cache->trans) return; /* Map the texture transfer. * Subsequent glBitmap calls will write into the texture image. */ cache->buffer = pipe_transfer_map(pipe, cache->texture, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, &cache->trans); /* init image to all 0xff */ memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT); }
/** * Upload data to a rectangular sub-region. Lots of choices how to do this: * * - memcpy by span to current destination * - upload data as new buffer and blit * * Currently always memcpy. */ static void st_surface_data(struct pipe_context *pipe, struct pipe_transfer *dst, unsigned dstx, unsigned dsty, const void *src, unsigned src_stride, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { void *map = pipe_transfer_map(pipe, dst); assert(dst->resource); util_copy_rect(map, dst->resource->format, dst->stride, dstx, dsty, width, height, src, src_stride, srcx, srcy); pipe_transfer_unmap(pipe, dst); }
static boolean wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride) { struct pipe_context *pipe = wdt->winsys->pipe; struct pipe_resource *tex = wdt->tex; struct pipe_transfer *tr; void *map; map = pipe_transfer_map(pipe, tex, 0, 0, PIPE_TRANSFER_READ_WRITE, 0, 0, wdt->tex->width0, wdt->tex->height0, &tr); if (!map) return FALSE; *stride = tr->stride; wdt->stride = tr->stride; pipe->transfer_unmap(pipe, tr); return TRUE; }
XA_EXPORT void * xa_surface_map(struct xa_context *ctx, struct xa_surface *srf, unsigned int usage) { void *map; unsigned int gallium_usage = 0; struct pipe_context *pipe = ctx->pipe; /* * A surface may only have a single map. */ if (srf->transfer) return NULL; if (usage & XA_MAP_READ) gallium_usage |= PIPE_TRANSFER_READ; if (usage & XA_MAP_WRITE) gallium_usage |= PIPE_TRANSFER_WRITE; if (usage & XA_MAP_MAP_DIRECTLY) gallium_usage |= PIPE_TRANSFER_MAP_DIRECTLY; if (usage & XA_MAP_UNSYNCHRONIZED) gallium_usage |= PIPE_TRANSFER_UNSYNCHRONIZED; if (usage & XA_MAP_DONTBLOCK) gallium_usage |= PIPE_TRANSFER_DONTBLOCK; if (usage & XA_MAP_DISCARD_WHOLE_RESOURCE) gallium_usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; if (!(gallium_usage & (PIPE_TRANSFER_READ_WRITE))) return NULL; map = pipe_transfer_map(pipe, srf->tex, 0, 0, gallium_usage, 0, 0, srf->tex->width0, srf->tex->height0, &srf->transfer); if (!map) return NULL; srf->mapping_pipe = pipe; return map; }
/** * Update the pixelmap texture with the contents of the R/G/B/A pixel maps. */ static void load_color_map_texture(struct gl_context *ctx, struct pipe_resource *pt) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_transfer *transfer; const GLuint rSize = ctx->PixelMaps.RtoR.Size; const GLuint gSize = ctx->PixelMaps.GtoG.Size; const GLuint bSize = ctx->PixelMaps.BtoB.Size; const GLuint aSize = ctx->PixelMaps.AtoA.Size; const uint texSize = pt->width0; uint *dest; uint i, j; dest = (uint *) pipe_transfer_map(pipe, pt, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, texSize, texSize, &transfer); /* Pack four 1D maps into a 2D texture: * R map is placed horizontally, indexed by S, in channel 0 * G map is placed vertically, indexed by T, in channel 1 * B map is placed horizontally, indexed by S, in channel 2 * A map is placed vertically, indexed by T, in channel 3 */ for (i = 0; i < texSize; i++) { for (j = 0; j < texSize; j++) { union util_color uc; int k = (i * texSize + j); float rgba[4]; rgba[0] = ctx->PixelMaps.RtoR.Map[j * rSize / texSize]; rgba[1] = ctx->PixelMaps.GtoG.Map[i * gSize / texSize]; rgba[2] = ctx->PixelMaps.BtoB.Map[j * bSize / texSize]; rgba[3] = ctx->PixelMaps.AtoA.Map[i * aSize / texSize]; util_pack_color(rgba, pt->format, &uc); *(dest + k) = uc.ui[0]; } } pipe_transfer_unmap(pipe, transfer); }
/* FIXME: dump resources, not surfaces... */ void debug_dump_surface(struct pipe_context *pipe, const char *prefix, struct pipe_surface *surface) { struct pipe_resource *texture; struct pipe_transfer *transfer; void *data; if (!surface) return; /* XXX: this doesn't necessarily work, as the driver may be using * temporary storage for the surface which hasn't been propagated * back into the texture. Need to nail down the semantics of views * and transfers a bit better before we can say if extra work needs * to be done here: */ texture = surface->texture; data = pipe_transfer_map(pipe, texture, surface->u.tex.level, surface->u.tex.first_layer, PIPE_TRANSFER_READ, 0, 0, surface->width, surface->height, &transfer); if (!data) return; debug_dump_image(prefix, texture->format, util_format_get_blocksize(texture->format), util_format_get_nblocksx(texture->format, surface->width), util_format_get_nblocksy(texture->format, surface->height), transfer->stride, data); pipe->transfer_unmap(pipe, transfer); }
static void drisw_update_tex_buffer(struct dri_drawable *drawable, struct dri_context *ctx, struct pipe_resource *res) { __DRIdrawable *dPriv = drawable->dPriv; struct st_context *st_ctx = (struct st_context *)ctx->st; struct pipe_context *pipe = st_ctx->pipe; struct pipe_transfer *transfer; char *map; int x, y, w, h; int ximage_stride, line; int cpp = util_format_get_blocksize(res->format); get_drawable_info(dPriv, &x, &y, &w, &h); map = pipe_transfer_map(pipe, res, 0, 0, // level, layer, PIPE_TRANSFER_WRITE, x, y, w, h, &transfer); /* Copy the Drawable content to the mapped texture buffer */ get_image(dPriv, x, y, w, h, map); /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. get_image() has a pitch rounded up to 4 bytes. */ ximage_stride = ((w * cpp) + 3) & -4; for (line = h-1; line; --line) { memmove(&map[line * transfer->stride], &map[line * ximage_stride], ximage_stride); } pipe_transfer_unmap(pipe, transfer); }
static void * wsw_dt_map(struct sw_winsys *ws, struct sw_displaytarget *dt, unsigned flags) { struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); struct pipe_context *pipe = wdt->winsys->pipe; struct pipe_resource *tex = wdt->tex; struct pipe_transfer *tr; void *ptr; if (!wdt->map_count) { assert(!wdt->transfer); ptr = pipe_transfer_map(pipe, tex, 0, 0, PIPE_TRANSFER_READ_WRITE, 0, 0, wdt->tex->width0, wdt->tex->height0, &tr); if (!ptr) goto err; wdt->transfer = tr; wdt->ptr = ptr; /* XXX Handle this case */ assert(tr->stride == wdt->stride); } wdt->map_count++; return wdt->ptr; err: pipe->transfer_unmap(pipe, tr); return NULL; }
/** * glGetTexImage() helper: decompress a compressed texture by rendering * a textured quad. Store the results in the user's buffer. */ static void decompress_with_blit(struct gl_context * ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_texture_image *stImage = st_texture_image(texImage); struct st_texture_object *stObj = st_texture_object(texImage->TexObject); const GLuint width = texImage->Width; const GLuint height = texImage->Height; struct pipe_resource *dst_texture; struct pipe_blit_info blit; unsigned bind = (PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_READ); struct pipe_transfer *tex_xfer; ubyte *map; /* create temp / dest surface */ if (!util_create_rgba_texture(pipe, width, height, bind, &dst_texture)) { _mesa_problem(ctx, "util_create_rgba_texture() failed " "in decompress_with_blit()"); return; } blit.src.resource = stObj->pt; blit.src.level = texImage->Level; blit.src.format = util_format_linear(stObj->pt->format); blit.dst.resource = dst_texture; blit.dst.level = 0; blit.dst.format = dst_texture->format; blit.src.box.x = blit.dst.box.x = 0; blit.src.box.y = blit.dst.box.y = 0; blit.src.box.z = 0; /* XXX compressed array textures? */ blit.dst.box.z = 0; blit.src.box.width = blit.dst.box.width = width; blit.src.box.height = blit.dst.box.height = height; blit.src.box.depth = blit.dst.box.depth = 1; blit.mask = PIPE_MASK_RGBA; blit.filter = PIPE_TEX_FILTER_NEAREST; blit.scissor_enable = FALSE; /* blit/render/decompress */ st->pipe->blit(st->pipe, &blit); pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); map = pipe_transfer_map(pipe, dst_texture, 0, 0, PIPE_TRANSFER_READ, 0, 0, width, height, &tex_xfer); if (!map) { goto end; } /* copy/pack data into user buffer */ if (_mesa_format_matches_format_and_type(stImage->base.TexFormat, format, type, ctx->Pack.SwapBytes)) { /* memcpy */ const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); /* map the dst_surface so we can read from it */ GLuint row; for (row = 0; row < height; row++) { GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); memcpy(dest, map, bytesPerRow); map += tex_xfer->stride; } pipe_transfer_unmap(pipe, tex_xfer); } else { /* format translation via floats */ GLuint row; enum pipe_format pformat = util_format_linear(dst_texture->format); GLfloat *rgba; rgba = malloc(width * 4 * sizeof(GLfloat)); if (!rgba) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); goto end; } for (row = 0; row < height; row++) { const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1, pformat, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); } free(rgba); } end: if (map) pipe_transfer_unmap(pipe, tex_xfer); _mesa_unmap_pbo_dest(ctx, &ctx->Pack); pipe_resource_reference(&dst_texture, NULL); }
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; ptr = pipe_transfer_map(ctx, samptex, 0, 0, /* level, layer */ PIPE_TRANSFER_READ, 0, 0, SIZE, SIZE, &t); /* x, y, width, height */ if (memcmp(ptr, tex2d, sizeof tex2d) != 0) { assert(0); exit(9); } ctx->transfer_unmap(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_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 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_sampler_states(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler); }
/** * Called via ctx->Driver.MapRenderbuffer. */ static void st_MapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint x, GLuint y, GLuint w, GLuint h, GLbitfield mode, GLubyte **mapOut, GLint *rowStrideOut) { struct st_context *st = st_context(ctx); struct st_renderbuffer *strb = st_renderbuffer(rb); struct pipe_context *pipe = st->pipe; const GLboolean invert = rb->Name == 0; unsigned usage; GLuint y2; GLubyte *map; if (strb->software) { /* software-allocated renderbuffer (probably an accum buffer) */ if (strb->data) { GLint bpp = _mesa_get_format_bytes(strb->Base.Format); GLint stride = _mesa_format_row_stride(strb->Base.Format, strb->Base.Width); *mapOut = (GLubyte *) strb->data + y * stride + x * bpp; *rowStrideOut = stride; } else { *mapOut = NULL; *rowStrideOut = 0; } return; } usage = 0x0; if (mode & GL_MAP_READ_BIT) usage |= PIPE_TRANSFER_READ; if (mode & GL_MAP_WRITE_BIT) usage |= PIPE_TRANSFER_WRITE; if (mode & GL_MAP_INVALIDATE_RANGE_BIT) usage |= PIPE_TRANSFER_DISCARD_RANGE; /* Note: y=0=bottom of buffer while y2=0=top of buffer. * 'invert' will be true for window-system buffers and false for * user-allocated renderbuffers and textures. */ if (invert) y2 = strb->Base.Height - y - h; else y2 = y; map = pipe_transfer_map(pipe, strb->texture, strb->surface->u.tex.level, strb->surface->u.tex.first_layer, usage, x, y2, w, h, &strb->transfer); if (map) { if (invert) { *rowStrideOut = -(int) strb->transfer->stride; map += (h - 1) * strb->transfer->stride; } else { *rowStrideOut = strb->transfer->stride; } *mapOut = map; } else { *mapOut = NULL; *rowStrideOut = 0; } }
PUBLIC void XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, const int *attrib_list) { struct st_context_iface *st = stapi->get_current(stapi); struct st_framebuffer_iface* stfbi = drawable->stfb; struct pipe_resource *res; int x, y, w, h; enum st_attachment_type st_attachment = xmesa_attachment_type(buffer); x = 0; y = 0; w = drawable->width; h = drawable->height; /* We need to validate our attachments before using them, * in case the texture doesn't exist yet. */ xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment); res = xmesa_get_attachment(stfbi, st_attachment); if (res) { struct pipe_context* pipe = xmesa_get_context(stfbi); enum pipe_format internal_format = res->format; struct pipe_transfer *tex_xfer; char *map; int line, ximage_stride; XImage *img; internal_format = choose_pixel_format(drawable->xm_visual); tex_xfer = pipe_get_transfer(pipe, res, 0, 0, /* level, layer */ PIPE_TRANSFER_WRITE, x, y, w, h); if (!tex_xfer) return; /* Grab the XImage that we want to turn into a texture. */ img = XGetImage(dpy, drawable->ws.drawable, x, y, w, h, AllPlanes, ZPixmap); if (!img) { pipe_transfer_destroy(pipe, tex_xfer); return; } map = pipe_transfer_map(pipe, tex_xfer); if (!map) { pipe_transfer_destroy(pipe, tex_xfer); return; } /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. We assume 32 bit pixels. */ ximage_stride = w * 4; for (line = 0; line < h; line++) memcpy(&map[line * tex_xfer->stride], &img->data[line * ximage_stride], ximage_stride); pipe_transfer_unmap(pipe, tex_xfer); pipe_transfer_destroy(pipe, tex_xfer); st->teximage(st, ST_TEXTURE_2D, 0, /* level */ internal_format, res, FALSE /* no mipmap */); } }
/** * Fallback for pipe->clear_render_target() function. * XXX this looks too hackish to be really useful. * cpp > 4 looks like a gross hack at best... * Plus can't use these transfer fallbacks when clearing * multisampled surfaces for instance. * Clears all bound layers. */ void util_clear_render_target(struct pipe_context *pipe, struct pipe_surface *dst, const union pipe_color_union *color, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { struct pipe_transfer *dst_trans; ubyte *dst_map; union util_color uc; unsigned max_layer; assert(dst->texture); if (!dst->texture) return; if (dst->texture->target == PIPE_BUFFER) { /* * The fill naturally works on the surface format, however * the transfer uses resource format which is just bytes for buffers. */ unsigned dx, w; unsigned pixstride = util_format_get_blocksize(dst->format); dx = (dst->u.buf.first_element + dstx) * pixstride; w = width * pixstride; max_layer = 0; dst_map = pipe_transfer_map(pipe, dst->texture, 0, 0, PIPE_TRANSFER_WRITE, dx, 0, w, 1, &dst_trans); } else { max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer; dst_map = pipe_transfer_map_3d(pipe, dst->texture, dst->u.tex.level, PIPE_TRANSFER_WRITE, dstx, dsty, dst->u.tex.first_layer, width, height, max_layer + 1, &dst_trans); } assert(dst_map); if (dst_map) { enum pipe_format format = dst->format; assert(dst_trans->stride > 0); if (util_format_is_pure_integer(format)) { /* * We expect int/uint clear values here, though some APIs * might disagree (but in any case util_pack_color() * couldn't handle it)... */ if (util_format_is_pure_sint(format)) { util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1); } else { assert(util_format_is_pure_uint(format)); util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1); } } else { util_pack_color(color->f, format, &uc); } util_fill_box(dst_map, dst->format, dst_trans->stride, dst_trans->layer_stride, 0, 0, 0, width, height, max_layer + 1, &uc); pipe->transfer_unmap(pipe, dst_trans); } }
/** * Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we * can't use a fragment shader to write stencil values. */ static void draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_renderbuffer *strb; enum pipe_transfer_usage usage; struct pipe_transfer *pt; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; GLint skipPixels; ubyte *stmap; struct gl_pixelstore_attrib clippedUnpack = *unpack; if (!zoom) { if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &clippedUnpack)) { /* totally clipped */ return; } } strb = st_renderbuffer(ctx->DrawBuffer-> Attachment[BUFFER_STENCIL].Renderbuffer); if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { y = ctx->DrawBuffer->Height - y - height; } if(format != GL_DEPTH_STENCIL && util_format_get_component_bits(strb->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0) usage = PIPE_TRANSFER_READ_WRITE; else usage = PIPE_TRANSFER_WRITE; pt = pipe_get_transfer(pipe, strb->texture, strb->rtt_level, strb->rtt_face + strb->rtt_slice, usage, x, y, width, height); stmap = pipe_transfer_map(pipe, pt); pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels); assert(pixels); /* if width > MAX_WIDTH, have to process image in chunks */ skipPixels = 0; while (skipPixels < width) { const GLint spanX = skipPixels; const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); GLint row; for (row = 0; row < height; row++) { GLubyte sValues[MAX_WIDTH]; GLuint zValues[MAX_WIDTH]; GLenum destType = GL_UNSIGNED_BYTE; const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels, width, height, format, type, row, skipPixels); _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues, type, source, &clippedUnpack, ctx->_ImageTransferState); if (format == GL_DEPTH_STENCIL) { _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, (1 << 24) - 1, type, source, &clippedUnpack); } if (zoom) { _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with " "zoom not complete"); } { GLint spanY; if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { spanY = height - row - 1; } else { spanY = row; } /* now pack the stencil (and Z) values in the dest format */ switch (pt->resource->format) { case PIPE_FORMAT_S8_USCALED: { ubyte *dest = stmap + spanY * pt->stride + spanX; assert(usage == PIPE_TRANSFER_WRITE); memcpy(dest, sValues, spanWidth); } break; case PIPE_FORMAT_Z24_UNORM_S8_USCALED: if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; assert(usage == PIPE_TRANSFER_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = zValues[k] | (sValues[k] << 24); } } else { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; assert(usage == PIPE_TRANSFER_READ_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24); } } break; case PIPE_FORMAT_S8_USCALED_Z24_UNORM: if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; assert(usage == PIPE_TRANSFER_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff); } } else { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; assert(usage == PIPE_TRANSFER_READ_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff); } } break; default: assert(0); } } } skipPixels += spanWidth; } _mesa_unmap_pbo_source(ctx, &clippedUnpack); /* unmap the stencil buffer */ pipe_transfer_unmap(pipe, pt); pipe->transfer_destroy(pipe, pt); }
void vegaReadPixels(void * data, VGint dataStride, VGImageFormat dataFormat, VGint sx, VGint sy, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; struct st_framebuffer *stfb = ctx->draw_buffer; struct st_renderbuffer *strb = stfb->strb; VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; VGfloat *df = (VGfloat*)temp; VGint i; VGubyte *dst = (VGubyte *)data; VGint xoffset = 0, yoffset = 0; if (!supported_image_format(dataFormat)) { vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); return; } if (!data || !is_aligned(data)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } if (width <= 0 || height <= 0) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } if (sx < 0) { xoffset = -sx; xoffset *= _vega_size_for_format(dataFormat); width += sx; sx = 0; } if (sy < 0) { yoffset = -sy; yoffset *= dataStride; height += sy; sy = 0; } if (sx + width > stfb->width || sy + height > stfb->height) { width = stfb->width - sx; height = stfb->height - sy; /* nothing to read */ if (width <= 0 || height <= 0) return; } { VGint y = (stfb->height - sy) - 1, yStep = -1; struct pipe_transfer *transfer; void *map; map = pipe_transfer_map(pipe, strb->texture, 0, 0, PIPE_TRANSFER_READ, 0, 0, sx + width, stfb->height - sy, &transfer); /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { #if 0 debug_printf("%d-%d == %d\n", sy, height, y); #endif pipe_get_tile_rgba(transfer, map, sx, y, width, 1, df); y += yStep; _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst + yoffset + xoffset); dst += dataStride; } pipe->transfer_unmap(pipe, transfer); } }
/** * glGetTexImage() helper: decompress a compressed texture by rendering * a textured quad. Store the results in the user's buffer. */ static void decompress_with_blit(struct gl_context * ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_texture_image *stImage = st_texture_image(texImage); struct st_texture_object *stObj = st_texture_object(texImage->TexObject); struct pipe_sampler_view *src_view; const GLuint width = texImage->Width; const GLuint height = texImage->Height; struct pipe_surface *dst_surface; struct pipe_resource *dst_texture; struct pipe_transfer *tex_xfer; unsigned bind = (PIPE_BIND_RENDER_TARGET | /* util_blit may choose to render */ PIPE_BIND_TRANSFER_READ); /* create temp / dest surface */ if (!util_create_rgba_surface(pipe, width, height, bind, &dst_texture, &dst_surface)) { _mesa_problem(ctx, "util_create_rgba_surface() failed " "in decompress_with_blit()"); return; } /* Disable conditional rendering. */ if (st->render_condition) { pipe->render_condition(pipe, NULL, 0); } /* Create sampler view that limits fetches to the source mipmap level */ { struct pipe_sampler_view sv_temp; u_sampler_view_default_template(&sv_temp, stObj->pt, stObj->pt->format); sv_temp.format = util_format_linear(sv_temp.format); sv_temp.u.tex.first_level = sv_temp.u.tex.last_level = texImage->Level; src_view = pipe->create_sampler_view(pipe, stObj->pt, &sv_temp); if (!src_view) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); return; } } /* blit/render/decompress */ util_blit_pixels_tex(st->blit, src_view, /* pipe_resource (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ 0, 0, /* dst x0, y0 */ width, height, /* dst x1, y1 */ 0.0, /* z */ PIPE_TEX_MIPFILTER_NEAREST); /* Restore conditional rendering state. */ if (st->render_condition) { pipe->render_condition(pipe, st->render_condition, st->condition_mode); } /* map the dst_surface so we can read from it */ tex_xfer = pipe_get_transfer(pipe, dst_texture, 0, 0, PIPE_TRANSFER_READ, 0, 0, width, height); pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); /* copy/pack data into user buffer */ if (_mesa_format_matches_format_and_type(stImage->base.TexFormat, format, type, ctx->Pack.SwapBytes)) { /* memcpy */ const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); ubyte *map = pipe_transfer_map(pipe, tex_xfer); GLuint row; for (row = 0; row < height; row++) { GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); memcpy(dest, map, bytesPerRow); map += tex_xfer->stride; } pipe_transfer_unmap(pipe, tex_xfer); } else { /* format translation via floats */ GLuint row; enum pipe_format pformat = util_format_linear(dst_texture->format); GLfloat *rgba; rgba = (GLfloat *) malloc(width * 4 * sizeof(GLfloat)); if (!rgba) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); goto end; } for (row = 0; row < height; row++) { const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1, pformat, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); } free(rgba); } end: _mesa_unmap_pbo_dest(ctx, &ctx->Pack); pipe->transfer_destroy(pipe, tex_xfer); /* destroy the temp / dest surface */ util_destroy_rgba_surface(dst_texture, dst_surface); pipe_sampler_view_release(pipe, &src_view); }
/** * Fallback for pipe->clear_stencil() function. * sw fallback doesn't look terribly useful here. * Plus can't use these transfer fallbacks when clearing * multisampled surfaces for instance. */ void util_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *dst, unsigned clear_flags, double depth, unsigned stencil, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { struct pipe_transfer *dst_trans; ubyte *dst_map; boolean need_rmw = FALSE; if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && util_format_is_depth_and_stencil(dst->format)) need_rmw = TRUE; assert(dst->texture); if (!dst->texture) return; dst_map = pipe_transfer_map(pipe, dst->texture, dst->u.tex.level, dst->u.tex.first_layer, (need_rmw ? PIPE_TRANSFER_READ_WRITE : PIPE_TRANSFER_WRITE), dstx, dsty, width, height, &dst_trans); assert(dst_map); if (dst_map) { unsigned dst_stride = dst_trans->stride; uint64_t zstencil = util_pack64_z_stencil(dst->texture->format, depth, stencil); unsigned i, j; assert(dst_trans->stride > 0); switch (util_format_get_blocksize(dst->format)) { case 1: assert(dst->format == PIPE_FORMAT_S8_UINT); if(dst_stride == width) memset(dst_map, (uint8_t) zstencil, height * width); else { for (i = 0; i < height; i++) { memset(dst_map, (uint8_t) zstencil, width); dst_map += dst_stride; } } break; case 2: assert(dst->format == PIPE_FORMAT_Z16_UNORM); for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst_map; for (j = 0; j < width; j++) *row++ = (uint16_t) zstencil; dst_map += dst_stride; } break; case 4: if (!need_rmw) { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst_map; for (j = 0; j < width; j++) *row++ = (uint32_t) zstencil; dst_map += dst_stride; } } else { uint32_t dst_mask; if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_UINT) dst_mask = 0xffffff00; else { assert(dst->format == PIPE_FORMAT_S8_UINT_Z24_UNORM); dst_mask = 0xffffff; } if (clear_flags & PIPE_CLEAR_DEPTH) dst_mask = ~dst_mask; for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst_map; for (j = 0; j < width; j++) { uint32_t tmp = *row & dst_mask; *row++ = tmp | ((uint32_t) zstencil & ~dst_mask); } dst_map += dst_stride; } } break; case 8: if (!need_rmw) { for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst_map; for (j = 0; j < width; j++) *row++ = zstencil; dst_map += dst_stride; } } else { uint64_t src_mask; if (clear_flags & PIPE_CLEAR_DEPTH) src_mask = 0x00000000ffffffffull; else src_mask = 0x000000ff00000000ull; for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst_map; for (j = 0; j < width; j++) { uint64_t tmp = *row & ~src_mask; *row++ = tmp | (zstencil & src_mask); } dst_map += dst_stride; } } break; default: assert(0); break; } pipe->transfer_unmap(pipe, dst_trans); } }
/** * Do a CopyTexSubImage operation using a read transfer from the source, * a write transfer to the destination and get_tile()/put_tile() to access * the pixels/texels. * * Note: srcY=0=TOP of renderbuffer */ static void fallback_copy_texsubimage(struct gl_context *ctx, struct st_renderbuffer *strb, struct st_texture_image *stImage, GLenum baseFormat, GLint destX, GLint destY, GLint destZ, GLint srcX, GLint srcY, GLsizei width, GLsizei height) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_transfer *src_trans; GLvoid *texDest; enum pipe_transfer_usage transfer_usage; void *map; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { srcY = strb->Base.Height - srcY - height; } map = pipe_transfer_map(pipe, strb->texture, strb->rtt_level, strb->rtt_face + strb->rtt_slice, PIPE_TRANSFER_READ, srcX, srcY, width, height, &src_trans); if ((baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) && util_format_is_depth_and_stencil(stImage->pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; else transfer_usage = PIPE_TRANSFER_WRITE; /* XXX this used to ignore destZ param */ texDest = st_texture_image_map(st, stImage, destZ, transfer_usage, destX, destY, width, height); if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) { const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F); GLint row, yStep; uint *data; /* determine bottom-to-top vs. top-to-bottom order for src buffer */ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { srcY = height - 1; yStep = -1; } else { srcY = 0; yStep = 1; } data = malloc(width * sizeof(uint)); if (data) { /* To avoid a large temp memory allocation, do copy row by row */ for (row = 0; row < height; row++, srcY += yStep) { pipe_get_tile_z(src_trans, map, 0, srcY, width, 1, data); if (scaleOrBias) { _mesa_scale_and_bias_depth_uint(ctx, width, data); } pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1, data); } } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage()"); } free(data); } else { /* RGBA format */ GLfloat *tempSrc = malloc(width * height * 4 * sizeof(GLfloat)); if (tempSrc && texDest) { const GLint dims = 2; const GLint dstRowStride = stImage->transfer->stride; struct gl_texture_image *texImage = &stImage->base; struct gl_pixelstore_attrib unpack = ctx->DefaultPacking; if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { unpack.Invert = GL_TRUE; } /* get float/RGBA image from framebuffer */ /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. */ pipe_get_tile_rgba_format(src_trans, map, 0, 0, width, height, util_format_linear(strb->texture->format), tempSrc); /* Store into texture memory. * Note that this does some special things such as pixel transfer * ops and format conversion. In particular, if the dest tex format * is actually RGBA but the user created the texture as GL_RGB we * need to fill-in/override the alpha channel with 1.0. */ _mesa_texstore(ctx, dims, texImage->_BaseFormat, texImage->TexFormat, dstRowStride, (GLubyte **) &texDest, width, height, 1, GL_RGBA, GL_FLOAT, tempSrc, /* src */ &unpack); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); } free(tempSrc); } st_texture_image_unmap(st, stImage); pipe->transfer_unmap(pipe, src_trans); }