/** * Bind a pipe surface to a texture object. After the call, * the texture object is marked dirty and will be (re-)validated. * * If this is the first surface bound, the texture object is said to * switch from normal to surface based. It will be cleared first in * this case. * * \param ps pipe surface to be unbound * \param target texture target * \param level image level * \param format internal format of the texture */ int st_bind_texture_surface(struct pipe_surface *ps, int target, int level, enum pipe_format format) { GET_CURRENT_CONTEXT(ctx); const GLuint unit = ctx->Texture.CurrentUnit; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *texObj; struct gl_texture_image *texImage; struct st_texture_object *stObj; struct st_texture_image *stImage; GLenum internalFormat; switch (target) { case ST_TEXTURE_2D: target = GL_TEXTURE_2D; break; case ST_TEXTURE_RECT: target = GL_TEXTURE_RECTANGLE_ARB; break; default: return 0; } /* map pipe format to base format for now */ if (pf_get_component_bits(format, PIPE_FORMAT_COMP_A) > 0) internalFormat = GL_RGBA; else internalFormat = GL_RGB; texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); stObj = st_texture_object(texObj); /* switch to surface based */ if (!stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); stObj->surface_based = GL_TRUE; } texImage = _mesa_get_tex_image(ctx, texObj, target, level); stImage = st_texture_image(texImage); _mesa_init_teximage_fields(ctx, target, texImage, ps->width, ps->height, 1, 0, internalFormat); texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, GL_RGBA, GL_UNSIGNED_BYTE); _mesa_set_fetch_functions(texImage, 2); pipe_texture_reference(&stImage->pt, ps->texture); _mesa_dirty_texobj(ctx, texObj, GL_TRUE); _mesa_unlock_texture(ctx, texObj); return 1; }
static boolean st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target, int level, enum pipe_format internal_format, struct pipe_resource *tex, boolean mipmap) { struct st_context *st = (struct st_context *) stctxi; struct gl_context *ctx = st->ctx; struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); struct gl_texture_object *texObj; struct gl_texture_image *texImage; struct st_texture_object *stObj; struct st_texture_image *stImage; GLenum internalFormat; GLuint width, height, depth; switch (target) { case ST_TEXTURE_1D: target = GL_TEXTURE_1D; break; case ST_TEXTURE_2D: target = GL_TEXTURE_2D; break; case ST_TEXTURE_3D: target = GL_TEXTURE_3D; break; case ST_TEXTURE_RECT: target = GL_TEXTURE_RECTANGLE_ARB; break; default: return FALSE; break; } texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); stObj = st_texture_object(texObj); /* switch to surface based */ if (!stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); stObj->surface_based = GL_TRUE; } texImage = _mesa_get_tex_image(ctx, texObj, target, level); stImage = st_texture_image(texImage); if (tex) { gl_format texFormat; /* * XXX When internal_format and tex->format differ, st_finalize_texture * needs to allocate a new texture with internal_format and copy the * texture here into the new one. It will result in surface_copy being * called on surfaces whose formats differ. * * To avoid that, internal_format is (wrongly) ignored here. A sane fix * is to use a sampler view. */ if (!st_sampler_compat_formats(tex->format, internal_format)) internal_format = tex->format; if (util_format_get_component_bits(internal_format, UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) internalFormat = GL_RGBA; else internalFormat = GL_RGB; texFormat = st_ChooseTextureFormat(ctx, internalFormat, GL_BGRA, GL_UNSIGNED_BYTE); _mesa_init_teximage_fields(ctx, texImage, tex->width0, tex->height0, 1, 0, internalFormat, texFormat); width = tex->width0; height = tex->height0; depth = tex->depth0; /* grow the image size until we hit level = 0 */ while (level > 0) { if (width != 1) width <<= 1; if (height != 1) height <<= 1; if (depth != 1) depth <<= 1; level--; } } else { _mesa_clear_texture_image(ctx, texImage); width = height = depth = 0; } pipe_resource_reference(&stImage->pt, tex); stObj->width0 = width; stObj->height0 = height; stObj->depth0 = depth; _mesa_dirty_texobj(ctx, texObj, GL_TRUE); _mesa_unlock_texture(ctx, texObj); return TRUE; }
/** * Make texture containing an image for glDrawPixels image. * If 'pixels' is NULL, leave the texture image data undefined. */ static struct pipe_texture * make_texture(struct st_context *st, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) { GLcontext *ctx = st->ctx; struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; const struct gl_texture_format *mformat; struct pipe_texture *pt; enum pipe_format pipeFormat; GLuint cpp; GLenum baseFormat; baseFormat = _mesa_base_format(format); mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type); assert(mformat); pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat); assert(pipeFormat); cpp = st_sizeof_format(pipeFormat); pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels); if (!pixels) return NULL; pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, 1, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) { _mesa_unmap_drawpix_pbo(ctx, unpack); return NULL; } { struct pipe_transfer *transfer; static const GLuint dstImageOffsets = 0; GLboolean success; GLubyte *dest; const GLbitfield imageTransferStateSave = ctx->_ImageTransferState; /* we'll do pixel transfer in a fragment shader */ ctx->_ImageTransferState = 0x0; transfer = st_no_flush_get_tex_transfer(st, pt, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, width, height); /* map texture transfer */ dest = screen->transfer_map(screen, transfer); /* Put image into texture transfer. * Note that the image is actually going to be upside down in * the texture. We deal with that with texcoords. */ success = mformat->StoreImage(ctx, 2, /* dims */ baseFormat, /* baseInternalFormat */ mformat, /* gl_texture_format */ dest, /* dest */ 0, 0, 0, /* dstX/Y/Zoffset */ transfer->stride, /* dstRowStride, bytes */ &dstImageOffsets, /* dstImageOffsets */ width, height, 1, /* size */ format, type, /* src format/type */ pixels, /* data source */ unpack); /* unmap */ screen->transfer_unmap(screen, transfer); screen->tex_transfer_destroy(transfer); assert(success); /* restore */ ctx->_ImageTransferState = imageTransferStateSave; } _mesa_unmap_drawpix_pbo(ctx, unpack); return pt; }