#include "main/teximage.h"
#include "main/texstore.h"
+#include "drivers/common/meta.h"
+
#include "intel_mipmap_tree.h"
#include "intel_buffer_objects.h"
#include "intel_batchbuffer.h"
#include "intel_tex.h"
#include "intel_blit.h"
#include "intel_fbo.h"
+#include "intel_image.h"
#include "brw_context.h"
struct intel_texture_image *intelImage,
bool expect_accelerated_upload)
{
- GLuint firstLevel;
GLuint lastLevel;
int width, height, depth;
GLuint i;
DBG("%s\n", __FUNCTION__);
- /* If this image disrespects BaseLevel, allocate from level zero.
- * Usually BaseLevel == 0, so it's unlikely to happen.
- */
- if (intelImage->base.Base.Level < intelObj->base.BaseLevel)
- firstLevel = 0;
- else
- firstLevel = intelObj->base.BaseLevel;
-
/* Figure out image dimensions at start level. */
- for (i = intelImage->base.Base.Level; i > firstLevel; i--) {
+ for (i = intelImage->base.Base.Level; i > 0; i--) {
width <<= 1;
if (height != 1)
height <<= 1;
*/
if ((intelObj->base.Sampler.MinFilter == GL_NEAREST ||
intelObj->base.Sampler.MinFilter == GL_LINEAR) &&
- intelImage->base.Base.Level == firstLevel &&
- firstLevel == 0) {
- lastLevel = firstLevel;
+ intelImage->base.Base.Level == 0 &&
+ !intelObj->base.GenerateMipmap) {
+ lastLevel = 0;
} else {
- lastLevel = (firstLevel +
- _mesa_get_tex_max_num_levels(intelObj->base.Target,
- width, height, depth) - 1);
+ lastLevel = _mesa_get_tex_max_num_levels(intelObj->base.Target,
+ width, height, depth) - 1;
}
return intel_miptree_create(brw,
intelObj->base.Target,
intelImage->base.Base.TexFormat,
- firstLevel,
+ 0,
lastLevel,
width,
height,
depth,
expect_accelerated_upload,
intelImage->base.Base.NumSamples,
- INTEL_MIPTREE_TILING_ANY);
+ INTEL_MIPTREE_TILING_ANY,
+ false);
}
/* XXX: Do this for TexSubImage also:
return false;
}
- src_buffer = intel_bufferobj_source(brw, pbo, 64, &src_offset);
- /* note: potential 64-bit ptr to 32-bit int cast */
- src_offset += (GLuint) (unsigned long) pixels;
-
int src_stride =
_mesa_image_row_stride(unpack, image->Width, format, type);
+ /* note: potential 64-bit ptr to 32-bit int cast */
+ src_offset = (GLuint) (unsigned long) pixels;
+ src_buffer = intel_bufferobj_buffer(brw, pbo,
+ src_offset, src_stride * image->Height);
+
struct intel_mipmap_tree *pbo_mt =
intel_miptree_create_for_bo(brw,
src_buffer,
intelImage->mt->format,
src_offset,
image->Width, image->Height,
- src_stride, I915_TILING_NONE);
+ src_stride);
if (!pbo_mt)
return false;
{
bool ok;
- DBG("%s target %s level %d %dx%dx%d\n", __FUNCTION__,
+ DBG("%s mesa_format %s target %s format %s type %s level %d %dx%dx%d\n",
+ __FUNCTION__, _mesa_get_format_name(texImage->TexFormat),
_mesa_lookup_enum_by_nr(texImage->TexObject->Target),
+ _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type),
texImage->Level, texImage->Width, texImage->Height, texImage->Depth);
ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
/**
- * Binds a region to a texture image, like it was uploaded by glTexImage2D().
+ * Binds a BO to a texture image, as if it was uploaded by glTexImage2D().
*
* Used for GLX_EXT_texture_from_pixmap and EGL image extensions,
*/
static void
-intel_set_texture_image_region(struct gl_context *ctx,
- struct gl_texture_image *image,
- struct intel_region *region,
- GLenum target,
- GLenum internalFormat,
- gl_format format,
- uint32_t offset,
- GLuint width,
- GLuint height,
- GLuint tile_x,
- GLuint tile_y)
+intel_set_texture_image_bo(struct gl_context *ctx,
+ struct gl_texture_image *image,
+ drm_intel_bo *bo,
+ GLenum target,
+ GLenum internalFormat,
+ mesa_format format,
+ uint32_t offset,
+ GLuint width, GLuint height,
+ GLuint pitch,
+ GLuint tile_x, GLuint tile_y)
{
struct brw_context *brw = brw_context(ctx);
struct intel_texture_image *intel_image = intel_texture_image(image);
ctx->Driver.FreeTextureImageBuffer(ctx, image);
- intel_image->mt = intel_miptree_create_layout(brw, target, image->TexFormat,
- 0, 0,
- width, height, 1,
- true, 0 /* num_samples */);
+ intel_image->mt = intel_miptree_create_for_bo(brw, bo, image->TexFormat,
+ 0, width, height, pitch);
if (intel_image->mt == NULL)
return;
- intel_region_reference(&intel_image->mt->region, region);
+ intel_image->mt->target = target;
intel_image->mt->total_width = width;
intel_image->mt->total_height = height;
intel_image->mt->level[0].slice[0].x_offset = tile_x;
intel_texobj->needs_validate = true;
intel_image->mt->offset = offset;
- assert(region->pitch % region->cpp == 0);
- intel_image->base.RowStride = region->pitch / region->cpp;
+ assert(pitch % intel_image->mt->cpp == 0);
+ intel_image->base.RowStride = pitch / intel_image->mt->cpp;
/* Immediately validate the image to the object. */
intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
struct gl_framebuffer *fb = dPriv->driverPrivate;
struct brw_context *brw = pDRICtx->driverPrivate;
struct gl_context *ctx = &brw->ctx;
- struct intel_texture_object *intelObj;
struct intel_renderbuffer *rb;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
int level = 0, internalFormat = 0;
- gl_format texFormat = MESA_FORMAT_NONE;
+ mesa_format texFormat = MESA_FORMAT_NONE;
texObj = _mesa_get_current_tex_object(ctx, target);
- intelObj = intel_texture_object(texObj);
- if (!intelObj)
+ if (!texObj)
return;
if (dPriv->lastStamp != dPriv->dri2.stamp ||
intel_update_renderbuffers(pDRICtx, dPriv);
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
- /* If the region isn't set, then intel_update_renderbuffers was unable
- * to get the buffers for the drawable.
+ /* If the miptree isn't set, then intel_update_renderbuffers was unable
+ * to get the BO for the drawable from the window system.
*/
if (!rb || !rb->mt)
return;
if (rb->mt->cpp == 4) {
if (texture_format == __DRI_TEXTURE_FORMAT_RGB) {
internalFormat = GL_RGB;
- texFormat = MESA_FORMAT_XRGB8888;
+ texFormat = MESA_FORMAT_B8G8R8X8_UNORM;
}
else {
internalFormat = GL_RGBA;
- texFormat = MESA_FORMAT_ARGB8888;
+ texFormat = MESA_FORMAT_B8G8R8A8_UNORM;
}
} else if (rb->mt->cpp == 2) {
internalFormat = GL_RGB;
- texFormat = MESA_FORMAT_RGB565;
+ texFormat = MESA_FORMAT_B5G6R5_UNORM;
}
_mesa_lock_texture(&brw->ctx, texObj);
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
intel_miptree_make_shareable(brw, rb->mt);
- intel_set_texture_image_region(ctx, texImage, rb->mt->region, target,
- internalFormat, texFormat, 0,
- rb->mt->region->width,
- rb->mt->region->height,
- 0, 0);
+ intel_set_texture_image_bo(ctx, texImage, rb->mt->bo, target,
+ internalFormat, texFormat, 0,
+ rb->Base.Base.Width,
+ rb->Base.Base.Height,
+ rb->mt->pitch,
+ 0, 0);
_mesa_unlock_texture(&brw->ctx, texObj);
}
+static GLboolean
+intel_bind_renderbuffer_tex_image(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ struct gl_texture_image *image)
+{
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+ struct intel_texture_image *intel_image = intel_texture_image(image);
+ struct gl_texture_object *texobj = image->TexObject;
+ struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
+
+ /* We can only handle RB allocated with AllocRenderbufferStorage, or
+ * window-system renderbuffers.
+ */
+ assert(!rb->TexImage);
+
+ if (!irb->mt)
+ return false;
+
+ _mesa_lock_texture(ctx, texobj);
+ _mesa_init_teximage_fields(ctx, image,
+ rb->Width, rb->Height, 1,
+ 0, rb->InternalFormat, rb->Format);
+ image->NumSamples = rb->NumSamples;
+
+ intel_miptree_reference(&intel_image->mt, irb->mt);
+
+ /* Immediately validate the image to the object. */
+ intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
+
+ intel_texobj->needs_validate = true;
+ _mesa_unlock_texture(ctx, texobj);
+
+ return true;
+}
+
void
intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
{
return;
}
- intel_set_texture_image_region(ctx, texImage, image->region,
- target, image->internal_format,
- image->format, image->offset,
- image->width, image->height,
- image->tile_x, image->tile_y);
+ intel_set_texture_image_bo(ctx, texImage, image->bo,
+ target, image->internal_format,
+ image->format, image->offset,
+ image->width, image->height,
+ image->pitch,
+ image->tile_x, image->tile_y);
+}
+
+static bool
+blit_texture_to_pbo(struct gl_context *ctx,
+ GLenum format, GLenum type,
+ GLvoid * pixels, struct gl_texture_image *texImage)
+{
+ struct intel_texture_image *intelImage = intel_texture_image(texImage);
+ struct brw_context *brw = brw_context(ctx);
+ const struct gl_pixelstore_attrib *pack = &ctx->Pack;
+ struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
+ GLuint dst_offset;
+ drm_intel_bo *dst_buffer;
+ GLenum target = texImage->TexObject->Target;
+
+ /* Check if we can use GPU blit to copy from the hardware texture
+ * format to the user's format/type.
+ * Note that GL's pixel transfer ops don't apply to glGetTexImage()
+ */
+
+ if (!_mesa_format_matches_format_and_type(intelImage->mt->format, format,
+ type, false))
+ {
+ perf_debug("%s: unsupported format, fallback to CPU mapping for PBO\n",
+ __FUNCTION__);
+
+ return false;
+ }
+
+ if (ctx->_ImageTransferState) {
+ perf_debug("%s: bad transfer state, fallback to CPU mapping for PBO\n",
+ __FUNCTION__);
+ return false;
+ }
+
+ if (pack->SwapBytes || pack->LsbFirst) {
+ perf_debug("%s: unsupported pack swap params\n",
+ __FUNCTION__);
+ return false;
+ }
+
+ if (target == GL_TEXTURE_1D_ARRAY ||
+ target == GL_TEXTURE_2D_ARRAY ||
+ target == GL_TEXTURE_CUBE_MAP_ARRAY ||
+ target == GL_TEXTURE_3D) {
+ perf_debug("%s: no support for multiple slices, fallback to CPU mapping "
+ "for PBO\n", __FUNCTION__);
+ return false;
+ }
+
+ int dst_stride = _mesa_image_row_stride(pack, texImage->Width, format, type);
+ bool dst_flip = false;
+ /* Mesa flips the dst_stride for ctx->Pack.Invert, our mt must have a
+ * normal dst_stride.
+ */
+ struct gl_pixelstore_attrib uninverted_pack = *pack;
+ if (ctx->Pack.Invert) {
+ dst_stride = -dst_stride;
+ dst_flip = true;
+ uninverted_pack.Invert = false;
+ }
+ dst_offset = (GLintptr) pixels;
+ dst_offset += _mesa_image_offset(2, &uninverted_pack, texImage->Width,
+ texImage->Height, format, type, 0, 0, 0);
+ dst_buffer = intel_bufferobj_buffer(brw, dst, dst_offset,
+ texImage->Height * dst_stride);
+
+ struct intel_mipmap_tree *pbo_mt =
+ intel_miptree_create_for_bo(brw,
+ dst_buffer,
+ intelImage->mt->format,
+ dst_offset,
+ texImage->Width, texImage->Height,
+ dst_stride);
+
+ if (!pbo_mt)
+ return false;
+
+ if (!intel_miptree_blit(brw,
+ intelImage->mt, texImage->Level, texImage->Face,
+ 0, 0, false,
+ pbo_mt, 0, 0,
+ 0, 0, dst_flip,
+ texImage->Width, texImage->Height, GL_COPY))
+ return false;
+
+ intel_miptree_release(&pbo_mt);
+
+ return true;
+}
+
+static void
+intel_get_tex_image(struct gl_context *ctx,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_image *texImage) {
+ DBG("%s\n", __FUNCTION__);
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* Using PBOs, so try the BLT based path. */
+ if (blit_texture_to_pbo(ctx, format, type, pixels, texImage))
+ return;
+
+ }
+
+ _mesa_meta_GetTexImage(ctx, format, type, pixels, texImage);
+
+ DBG("%s - DONE\n", __FUNCTION__);
}
void
{
functions->TexImage = intelTexImage;
functions->EGLImageTargetTexture2D = intel_image_target_texture_2d;
+ functions->BindRenderbufferTexImage = intel_bind_renderbuffer_tex_image;
+ functions->GetTexImage = intel_get_tex_image;
}