/** * Print framebuffer info to stderr, for debugging. */ void _mesa_print_framebuffer(const struct gl_framebuffer *fb) { GLuint i; fprintf(stderr, "Mesa Framebuffer %u at %p\n", fb->Name, (void *) fb); fprintf(stderr, " Size: %u x %u Status: %s\n", fb->Width, fb->Height, _mesa_enum_to_string(fb->_Status)); fprintf(stderr, " Attachments:\n"); for (i = 0; i < BUFFER_COUNT; i++) { const struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; if (att->Type == GL_TEXTURE) { const struct gl_texture_image *texImage = att->Renderbuffer->TexImage; fprintf(stderr, " %2d: Texture %u, level %u, face %u, slice %u, complete %d\n", i, att->Texture->Name, att->TextureLevel, att->CubeMapFace, att->Zoffset, att->Complete); fprintf(stderr, " Size: %u x %u x %u Format %s\n", texImage->Width, texImage->Height, texImage->Depth, _mesa_get_format_name(texImage->TexFormat)); } else if (att->Type == GL_RENDERBUFFER) { fprintf(stderr, " %2d: Renderbuffer %u, complete %d\n", i, att->Renderbuffer->Name, att->Complete); fprintf(stderr, " Size: %u x %u Format %s\n", att->Renderbuffer->Width, att->Renderbuffer->Height, _mesa_get_format_name(att->Renderbuffer->Format)); } else { fprintf(stderr, " %2d: none\n", i); } } }
static void intel_miptree_copy_slice_sw(struct intel_context *intel, struct intel_mipmap_tree *dst_mt, struct intel_mipmap_tree *src_mt, int level, int slice, int width, int height) { void *src, *dst; int src_stride, dst_stride; int cpp = dst_mt->cpp; intel_miptree_map(intel, src_mt, level, slice, 0, 0, width, height, GL_MAP_READ_BIT, &src, &src_stride); intel_miptree_map(intel, dst_mt, level, slice, 0, 0, width, height, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, &dst, &dst_stride); DBG("sw blit %s mt %p %p/%d -> %s mt %p %p/%d (%dx%d)\n", _mesa_get_format_name(src_mt->format), src_mt, src, src_stride, _mesa_get_format_name(dst_mt->format), dst_mt, dst, dst_stride, width, height); int row_size = cpp * width; if (src_stride == row_size && dst_stride == row_size) { memcpy(dst, src, row_size * height); } else { for (int i = 0; i < height; i++) { memcpy(dst, src, row_size); dst += dst_stride; src += src_stride; } } intel_miptree_unmap(intel, dst_mt, level, slice); intel_miptree_unmap(intel, src_mt, level, slice); }
static void intel_miptree_copy_slice(struct intel_context *intel, struct intel_mipmap_tree *dst_mt, struct intel_mipmap_tree *src_mt, int level, int face, int depth) { mesa_format format = src_mt->format; uint32_t width = src_mt->level[level].width; uint32_t height = src_mt->level[level].height; int slice; if (face > 0) slice = face; else slice = depth; assert(depth < src_mt->level[level].depth); assert(src_mt->format == dst_mt->format); if (dst_mt->compressed) { height = ALIGN(height, dst_mt->align_h) / dst_mt->align_h; width = ALIGN(width, dst_mt->align_w); } uint32_t dst_x, dst_y, src_x, src_y; intel_miptree_get_image_offset(dst_mt, level, slice, &dst_x, &dst_y); intel_miptree_get_image_offset(src_mt, level, slice, &src_x, &src_y); DBG("validate blit mt %s %p %d,%d/%d -> mt %s %p %d,%d/%d (%dx%d)\n", _mesa_get_format_name(src_mt->format), src_mt, src_x, src_y, src_mt->region->pitch, _mesa_get_format_name(dst_mt->format), dst_mt, dst_x, dst_y, dst_mt->region->pitch, width, height); if (!intel_miptree_blit(intel, src_mt, level, slice, 0, 0, false, dst_mt, level, slice, 0, 0, false, width, height, GL_COPY)) { perf_debug("miptree validate blit for %s failed\n", _mesa_get_format_name(format)); intel_miptree_copy_slice_sw(intel, dst_mt, src_mt, level, slice, width, height); } }
static GLboolean intel_alloc_private_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct intel_context *intel = intel_context(ctx); struct intel_renderbuffer *irb = intel_renderbuffer(rb); assert(rb->Format != MESA_FORMAT_NONE); rb->Width = width; rb->Height = height; rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); intel_miptree_release(&irb->mt); DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, _mesa_lookup_enum_by_nr(internalFormat), _mesa_get_format_name(rb->Format), width, height); if (width == 0 || height == 0) return true; irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format, width, height); if (!irb->mt) return false; return true; }
/** * Called via glRenderbufferStorageEXT() to set the format and allocate * storage for a user-created renderbuffer. */ GLboolean intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct intel_context *intel = intel_context(ctx); struct intel_renderbuffer *irb = intel_renderbuffer(rb); ASSERT(rb->Name != 0); switch (internalFormat) { default: /* Use the same format-choice logic as for textures. * Renderbuffers aren't any different from textures for us, * except they're less useful because you can't texture with * them. */ rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat, GL_NONE, GL_NONE); break; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: /* These aren't actual texture formats, so force them here. */ if (intel->has_separate_stencil) { rb->Format = MESA_FORMAT_S8; } else { assert(!intel->must_use_separate_stencil); rb->Format = MESA_FORMAT_S8_Z24; } break; } rb->Width = width; rb->Height = height; rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); intel_miptree_release(&irb->mt); DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, _mesa_lookup_enum_by_nr(internalFormat), _mesa_get_format_name(rb->Format), width, height); irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format, width, height); if (!irb->mt) return false; if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { bool ok = intel_miptree_alloc_hiz(intel, irb->mt); if (!ok) { intel_miptree_release(&irb->mt); return false; } } return true; }
/** * Apply depth (Z) buffer testing to the span. * \return approx number of pixels that passed (only zero is reliable) */ GLuint _swrast_depth_test_span(struct gl_context *ctx, SWspan *span) { struct gl_framebuffer *fb = ctx->DrawBuffer; struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; const GLint bpp = _mesa_get_format_bytes(rb->Format); void *zStart; const GLuint count = span->end; const GLuint *fragZ = span->array->z; GLubyte *mask = span->array->mask; void *zBufferVals; GLuint *zBufferTemp = NULL; GLuint passed; GLuint zBits = _mesa_get_format_bits(rb->Format, GL_DEPTH_BITS); GLboolean ztest16 = GL_FALSE; if (span->arrayMask & SPAN_XY) zStart = NULL; else zStart = _swrast_pixel_address(rb, span->x, span->y); if (rb->Format == MESA_FORMAT_Z_UNORM16 && !(span->arrayMask & SPAN_XY)) { /* directly read/write row of 16-bit Z values */ zBufferVals = zStart; ztest16 = GL_TRUE; } else if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) { /* directly read/write row of 32-bit Z values */ zBufferVals = zStart; } else { if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED) { _mesa_problem(ctx, "Incorrectly writing swrast's integer depth " "values to %s depth buffer", _mesa_get_format_name(rb->Format)); } /* copy Z buffer values into temp buffer (32-bit Z values) */ zBufferTemp = malloc(count * sizeof(GLuint)); if (!zBufferTemp) return 0; if (span->arrayMask & SPAN_XY) { get_z32_values(ctx, rb, count, span->array->x, span->array->y, zBufferTemp); } else { _mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp); } if (zBits == 24) { GLuint i; /* Convert depth buffer values from 32 to 24 bits to match the * fragment Z values generated by rasterization. */ for (i = 0; i < count; i++) { zBufferTemp[i] >>= 8; } } else if (zBits == 16) {
void GLAPIENTRY _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (getcompressedteximage_error_check(ctx, target, level, img)) { return; } if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) { /* not an error, do nothing */ return; } texObj = _mesa_get_current_tex_object(ctx, target); texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { _mesa_debug(ctx, "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n", texObj->Name, _mesa_get_format_name(texImage->TexFormat), texImage->Width, texImage->Height); } _mesa_lock_texture(ctx, texObj); { ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj, texImage); } _mesa_unlock_texture(ctx, texObj); }
static GLuint translate_texture_format(gl_format mesa_format, GLenum DepthMode) { switch (mesa_format) { case MESA_FORMAT_L8: return MAPSURF_8BIT | MT_8BIT_L8; case MESA_FORMAT_I8: return MAPSURF_8BIT | MT_8BIT_I8; case MESA_FORMAT_A8: return MAPSURF_8BIT | MT_8BIT_A8; case MESA_FORMAT_AL88: return MAPSURF_16BIT | MT_16BIT_AY88; case MESA_FORMAT_RGB565: return MAPSURF_16BIT | MT_16BIT_RGB565; case MESA_FORMAT_ARGB1555: return MAPSURF_16BIT | MT_16BIT_ARGB1555; case MESA_FORMAT_ARGB4444: return MAPSURF_16BIT | MT_16BIT_ARGB4444; case MESA_FORMAT_ARGB8888: return MAPSURF_32BIT | MT_32BIT_ARGB8888; case MESA_FORMAT_XRGB8888: return MAPSURF_32BIT | MT_32BIT_XRGB8888; case MESA_FORMAT_RGBA8888_REV: return MAPSURF_32BIT | MT_32BIT_ABGR8888; case MESA_FORMAT_YCBCR_REV: return (MAPSURF_422 | MT_422_YCRCB_NORMAL); case MESA_FORMAT_YCBCR: return (MAPSURF_422 | MT_422_YCRCB_SWAPY); case MESA_FORMAT_RGB_FXT1: case MESA_FORMAT_RGBA_FXT1: return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); case MESA_FORMAT_Z16: if (DepthMode == GL_ALPHA) return (MAPSURF_16BIT | MT_16BIT_A16); else if (DepthMode == GL_INTENSITY) return (MAPSURF_16BIT | MT_16BIT_I16); else return (MAPSURF_16BIT | MT_16BIT_L16); case MESA_FORMAT_RGBA_DXT1: case MESA_FORMAT_RGB_DXT1: return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); case MESA_FORMAT_RGBA_DXT3: return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); case MESA_FORMAT_RGBA_DXT5: return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); case MESA_FORMAT_S8_Z24: case MESA_FORMAT_X8_Z24: if (DepthMode == GL_ALPHA) return (MAPSURF_32BIT | MT_32BIT_x8A24); else if (DepthMode == GL_INTENSITY) return (MAPSURF_32BIT | MT_32BIT_x8I24); else return (MAPSURF_32BIT | MT_32BIT_x8L24); default: fprintf(stderr, "%s: bad image format %s\n", __FUNCTION__, _mesa_get_format_name(mesa_format)); abort(); return 0; } }
static void radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); gl_format mesa_format; int i; for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { struct gl_renderbuffer_attachment *att; if (i == -2) { att = &fb->Attachment[BUFFER_DEPTH]; } else if (i == -1) { att = &fb->Attachment[BUFFER_STENCIL]; } else { att = &fb->Attachment[BUFFER_COLOR0 + i]; } if (att->Type == GL_TEXTURE) { mesa_format = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->TexFormat; } else { /* All renderbuffer formats are renderable, but not sampable */ continue; } if (!radeon->vtbl.is_format_renderable(mesa_format)){ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; radeon_print(RADEON_TEXTURE, RADEON_TRACE, "%s: HW doesn't support format %s as output format of attachment %d\n", __FUNCTION__, _mesa_get_format_name(mesa_format), i); return; } } }
/** * Determine if fast color clear supports the given clear color. * * Fast color clear can only clear to color values of 1.0 or 0.0. At the * moment we only support floating point, unorm, and snorm buffers. */ static bool is_color_fast_clear_compatible(struct brw_context *brw, mesa_format format, const union gl_color_union *color) { if (_mesa_is_format_integer_color(format)) { if (brw->gen >= 8) { perf_debug("Integer fast clear not enabled for (%s)", _mesa_get_format_name(format)); } return false; } for (int i = 0; i < 4; i++) { if (!_mesa_format_has_color_component(format, i)) { continue; } if (brw->gen < 9 && color->f[i] != 0.0f && color->f[i] != 1.0f) { return false; } } return true; }
/** * @param for_bo Indicates that the caller is * intel_miptree_create_for_bo(). If true, then do not create * \c stencil_mt. */ struct intel_mipmap_tree * intel_miptree_create_layout(struct intel_context *intel, GLenum target, mesa_format format, GLuint first_level, GLuint last_level, GLuint width0, GLuint height0, GLuint depth0, bool for_bo) { struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); if (!mt) return NULL; DBG("%s target %s format %s level %d..%d <-- %p\n", __func__, _mesa_enum_to_string(target), _mesa_get_format_name(format), first_level, last_level, mt); mt->target = target_to_target(target); mt->format = format; mt->first_level = first_level; mt->last_level = last_level; mt->logical_width0 = width0; mt->logical_height0 = height0; mt->logical_depth0 = depth0; /* The cpp is bytes per (1, blockheight)-sized block for compressed * textures. This is why you'll see divides by blockheight all over */ unsigned bw, bh; _mesa_get_format_block_size(format, &bw, &bh); assert(_mesa_get_format_bytes(mt->format) % bw == 0); mt->cpp = _mesa_get_format_bytes(mt->format) / bw; mt->compressed = _mesa_is_format_compressed(format); mt->refcount = 1; if (target == GL_TEXTURE_CUBE_MAP) { assert(depth0 == 1); depth0 = 6; } mt->physical_width0 = width0; mt->physical_height0 = height0; mt->physical_depth0 = depth0; intel_get_texture_alignment_unit(intel, mt->format, &mt->align_w, &mt->align_h); (void) intel; if (intel->is_945) i945_miptree_layout(mt); else i915_miptree_layout(mt); return mt; }
/** * Called via glRenderbufferStorageEXT() to set the format and allocate * storage for a user-created renderbuffer. */ static GLboolean intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct brw_context *brw = brw_context(ctx); struct intel_screen *screen = brw->intelScreen; struct intel_renderbuffer *irb = intel_renderbuffer(rb); rb->NumSamples = intel_quantize_num_samples(screen, rb->NumSamples); switch (internalFormat) { default: /* Use the same format-choice logic as for textures. * Renderbuffers aren't any different from textures for us, * except they're less useful because you can't texture with * them. */ rb->Format = ctx->Driver.ChooseTextureFormat(ctx, GL_TEXTURE_2D, internalFormat, GL_NONE, GL_NONE); break; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: /* These aren't actual texture formats, so force them here. */ if (brw->has_separate_stencil) { rb->Format = MESA_FORMAT_S8; } else { assert(!brw->must_use_separate_stencil); rb->Format = MESA_FORMAT_S8_Z24; } break; } rb->Width = width; rb->Height = height; rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); intel_miptree_release(&irb->mt); DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, _mesa_lookup_enum_by_nr(internalFormat), _mesa_get_format_name(rb->Format), width, height); if (width == 0 || height == 0) return true; irb->mt = intel_miptree_create_for_renderbuffer(brw, rb->Format, width, height, rb->NumSamples); if (!irb->mt) return false; return true; }
static void intelTexImage(struct gl_context * ctx, GLuint dims, struct gl_texture_image *texImage, GLenum format, GLenum type, const void *pixels, const struct gl_pixelstore_attrib *unpack) { struct intel_texture_image *intelImage = intel_texture_image(texImage); bool ok; bool tex_busy = intelImage->mt && drm_intel_bo_busy(intelImage->mt->bo); DBG("%s mesa_format %s target %s format %s type %s level %d %dx%dx%d\n", __func__, _mesa_get_format_name(texImage->TexFormat), _mesa_enum_to_string(texImage->TexObject->Target), _mesa_enum_to_string(format), _mesa_enum_to_string(type), texImage->Level, texImage->Width, texImage->Height, texImage->Depth); /* Allocate storage for texture data. */ if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); return; } assert(intelImage->mt); if (intelImage->mt->format == MESA_FORMAT_S_UINT8) intelImage->mt->r8stencil_needs_update = true; ok = _mesa_meta_pbo_TexSubImage(ctx, dims, texImage, 0, 0, 0, texImage->Width, texImage->Height, texImage->Depth, format, type, pixels, tex_busy, unpack); if (ok) return; ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage, 0, 0, 0, /*x,y,z offsets*/ texImage->Width, texImage->Height, texImage->Depth, format, type, pixels, unpack, false /*allocate_storage*/); if (ok) return; DBG("%s: upload image %dx%dx%d pixels %p\n", __func__, texImage->Width, texImage->Height, texImage->Depth, pixels); _mesa_store_teximage(ctx, dims, texImage, format, type, pixels, unpack); }
/** * \see dd_function_table::MapRenderbuffer */ static void intel_map_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint x, GLuint y, GLuint w, GLuint h, GLbitfield mode, GLubyte **out_map, GLint *out_stride) { struct intel_context *intel = intel_context(ctx); struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; struct intel_renderbuffer *irb = intel_renderbuffer(rb); void *map; int stride; if (srb->Buffer) { /* this is a malloc'd renderbuffer (accum buffer), not an irb */ GLint bpp = _mesa_get_format_bytes(rb->Format); GLint rowStride = srb->RowStride; *out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp; *out_stride = rowStride; return; } /* We sometimes get called with this by our intel_span.c usage. */ if (!irb->mt) { *out_map = NULL; *out_stride = 0; return; } /* For a window-system renderbuffer, we need to flip the mapping we receive * upside-down. So we need to ask for a rectangle on flipped vertically, and * we then return a pointer to the bottom of it with a negative stride. */ if (rb->Name == 0) { y = rb->Height - y - h; } intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer, x, y, w, h, mode, &map, &stride); if (rb->Name == 0) { map += (h - 1) * stride; stride = -stride; } DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n", __FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format), x, y, w, h, map, stride); *out_map = map; *out_stride = stride; }
uint32_t brw_depthbuffer_format(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb = ctx->DrawBuffer; struct intel_renderbuffer *drb = intel_get_renderbuffer(fb, BUFFER_DEPTH); struct intel_renderbuffer *srb; if (!drb && (srb = intel_get_renderbuffer(fb, BUFFER_STENCIL)) && !srb->mt->stencil_mt && (intel_rb_format(srb) == MESA_FORMAT_S8_Z24 || intel_rb_format(srb) == MESA_FORMAT_Z32_FLOAT_X24S8)) { drb = srb; } if (!drb) return BRW_DEPTHFORMAT_D32_FLOAT; switch (drb->mt->format) { case MESA_FORMAT_Z16: return BRW_DEPTHFORMAT_D16_UNORM; case MESA_FORMAT_Z32_FLOAT: return BRW_DEPTHFORMAT_D32_FLOAT; case MESA_FORMAT_X8_Z24: if (intel->gen >= 6) { return BRW_DEPTHFORMAT_D24_UNORM_X8_UINT; } else { /* Use D24_UNORM_S8, not D24_UNORM_X8. * * D24_UNORM_X8 was not introduced until Gen5. (See the Ironlake PRM, * Volume 2, Part 1, Section 8.4.6 "Depth/Stencil Buffer State", Bits * 3DSTATE_DEPTH_BUFFER.Surface_Format). * * However, on Gen5, D24_UNORM_X8 may be used only if separate * stencil is enabled, and we never enable it. From the Ironlake PRM, * same section as above, Bit 3DSTATE_DEPTH_BUFFER.Separate_Stencil_Buffer_Enable: * If this field is disabled, the Surface Format of the depth * buffer cannot be D24_UNORM_X8_UINT. */ return BRW_DEPTHFORMAT_D24_UNORM_S8_UINT; } case MESA_FORMAT_S8_Z24: return BRW_DEPTHFORMAT_D24_UNORM_S8_UINT; case MESA_FORMAT_Z32_FLOAT_X24S8: return BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT; default: _mesa_problem(ctx, "Unexpected depth format %s\n", _mesa_get_format_name(intel_rb_format(drb))); return BRW_DEPTHFORMAT_D16_UNORM; } }
/** * Called by Mesa when rendering to a texture is done. */ static void intel_finish_render_texture(struct gl_context * ctx, struct gl_renderbuffer *rb) { struct brw_context *brw = brw_context(ctx); DBG("Finish render %s texture\n", _mesa_get_format_name(rb->Format)); /* Since we've (probably) rendered to the texture and will (likely) use * it in the texture domain later on in this batchbuffer, flush the * batch. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer like GEM does in the kernel. */ intel_batchbuffer_emit_mi_flush(brw); }
/** * This is the implementation for glGetnTexImageARB, glGetTextureImage, * and glGetTexImage. * * Requires caller to pass in texImage object because _mesa_GetTextureImage * must handle the GL_TEXTURE_CUBE_MAP target. * * \param target texture target. * \param level image level. * \param format pixel data format for returned image. * \param type pixel data type for returned image. * \param bufSize size of the pixels data buffer. * \param pixels returned pixel data. * \param dsa True when the caller is an ARB_direct_state_access function, * false otherwise */ void _mesa_get_texture_image(struct gl_context *ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage, GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *pixels, bool dsa) { assert(texObj); assert(texImage); FLUSH_VERTICES(ctx, 0); /* * Legal target checking has been moved up to GetnTexImage and * GetTextureImage so that it can be caught before receiving a NULL * texImage object and exiting. */ if (getteximage_error_check(ctx, texImage, target, level, format, type, bufSize, pixels, dsa)) { return; } if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { /* not an error, do nothing */ return; } if (_mesa_is_zero_size_texture(texImage)) return; if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { _mesa_debug(ctx, "glGetTex%sImage(tex %u) format = %s, w=%d, h=%d," " dstFmt=0x%x, dstType=0x%x\n", dsa ? "ture": "", texObj->Name, _mesa_get_format_name(texImage->TexFormat), texImage->Width, texImage->Height, format, type); } _mesa_lock_texture(ctx, texObj); { ctx->Driver.GetTexImage(ctx, format, type, pixels, texImage); } _mesa_unlock_texture(ctx, texObj); }
static GLboolean radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb, struct gl_texture_image *texImage) { radeon_print(RADEON_TEXTURE, RADEON_TRACE, "%s(%p, rrb %p, texImage %p, texFormat %s) \n", __func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat)); switch (texImage->TexFormat) { case MESA_FORMAT_RGBA8888: case MESA_FORMAT_RGBA8888_REV: case MESA_FORMAT_ARGB8888: case MESA_FORMAT_ARGB8888_REV: case MESA_FORMAT_XRGB8888: case MESA_FORMAT_XRGB8888_REV: case MESA_FORMAT_RGB565: case MESA_FORMAT_RGB565_REV: case MESA_FORMAT_RGBA5551: case MESA_FORMAT_ARGB1555: case MESA_FORMAT_ARGB1555_REV: case MESA_FORMAT_ARGB4444: case MESA_FORMAT_ARGB4444_REV: rrb->base.DataType = GL_UNSIGNED_BYTE; break; case MESA_FORMAT_Z16: rrb->base.DataType = GL_UNSIGNED_SHORT; break; case MESA_FORMAT_X8_Z24: rrb->base.DataType = GL_UNSIGNED_INT; break; case MESA_FORMAT_S8_Z24: rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; break; } rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat); rrb->pitch = texImage->Width * rrb->cpp; rrb->base.Format = texImage->TexFormat; rrb->base.InternalFormat = texImage->InternalFormat; rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat); rrb->base.Width = texImage->Width; rrb->base.Height = texImage->Height; rrb->base.Delete = radeon_delete_renderbuffer; rrb->base.AllocStorage = radeon_nop_alloc_storage; return GL_TRUE; }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_renderbuffer *rb = att->Renderbuffer; struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct gl_texture_image *image = rb->TexImage; struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _swrast_render_texture(ctx, fb, att); return; } intel_miptree_check_level_layer(mt, att->TextureLevel, layer); if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _swrast_render_texture(ctx, fb, att); return; } DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, image->Depth, rb->RefCount); /* update drawing region, etc */ intel_draw_buffer(ctx); }
/** * \see dd_function_table::UnmapRenderbuffer */ static void intel_unmap_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) { struct intel_context *intel = intel_context(ctx); struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; struct intel_renderbuffer *irb = intel_renderbuffer(rb); DBG("%s: rb %d (%s)\n", __FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format)); if (srb->Buffer) { /* this is a malloc'd renderbuffer (accum buffer) */ /* nothing to do */ return; } intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer); }
static GLuint translate_texture_format(GLuint mesa_format) { switch (mesa_format) { case MESA_FORMAT_L8: return MAPSURF_8BIT | MT_8BIT_L8; case MESA_FORMAT_I8: return MAPSURF_8BIT | MT_8BIT_I8; case MESA_FORMAT_A8: return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */ case MESA_FORMAT_AL88: return MAPSURF_16BIT | MT_16BIT_AY88; case MESA_FORMAT_RGB565: return MAPSURF_16BIT | MT_16BIT_RGB565; case MESA_FORMAT_ARGB1555: return MAPSURF_16BIT | MT_16BIT_ARGB1555; case MESA_FORMAT_ARGB4444: return MAPSURF_16BIT | MT_16BIT_ARGB4444; case MESA_FORMAT_ARGB8888: return MAPSURF_32BIT | MT_32BIT_ARGB8888; case MESA_FORMAT_XRGB8888: return MAPSURF_32BIT | MT_32BIT_XRGB8888; case MESA_FORMAT_YCBCR_REV: return (MAPSURF_422 | MT_422_YCRCB_NORMAL); case MESA_FORMAT_YCBCR: return (MAPSURF_422 | MT_422_YCRCB_SWAPY); case MESA_FORMAT_RGB_FXT1: case MESA_FORMAT_RGBA_FXT1: return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); case MESA_FORMAT_RGBA_DXT1: case MESA_FORMAT_RGB_DXT1: return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); case MESA_FORMAT_RGBA_DXT3: return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); case MESA_FORMAT_RGBA_DXT5: return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); default: fprintf(stderr, "%s: bad image format %s\n", __FUNCTION__, _mesa_get_format_name(mesa_format)); abort(); return 0; } }
static void intel_miptree_map_blit(struct intel_context *intel, struct intel_mipmap_tree *mt, struct intel_miptree_map *map, unsigned int level, unsigned int slice) { map->mt = intel_miptree_create(intel, GL_TEXTURE_2D, mt->format, 0, 0, map->w, map->h, 1, false, INTEL_MIPTREE_TILING_NONE); if (!map->mt) { fprintf(stderr, "Failed to allocate blit temporary\n"); goto fail; } map->stride = map->mt->region->pitch; if (!intel_miptree_blit(intel, mt, level, slice, map->x, map->y, false, map->mt, 0, 0, 0, 0, false, map->w, map->h, GL_COPY)) { fprintf(stderr, "Failed to blit\n"); goto fail; } intel_batchbuffer_flush(intel); map->ptr = intel_miptree_map_raw(intel, map->mt); DBG("%s: %d,%d %dx%d from mt %p (%s) %d,%d = %p/%d\n", __func__, map->x, map->y, map->w, map->h, mt, _mesa_get_format_name(mt->format), level, slice, map->ptr, map->stride); return; fail: intel_miptree_release(&map->mt); map->ptr = NULL; map->stride = 0; }
/** * Determine if fast color clear supports the given clear color. * * Fast color clear can only clear to color values of 1.0 or 0.0. At the * moment we only support floating point, unorm, and snorm buffers. */ bool brw_is_color_fast_clear_compatible(struct brw_context *brw, const struct intel_mipmap_tree *mt, const union gl_color_union *color) { const struct gen_device_info *devinfo = &brw->screen->devinfo; const struct gl_context *ctx = &brw->ctx; /* If we're mapping the render format to a different format than the * format we use for texturing then it is a bit questionable whether it * should be possible to use a fast clear. Although we only actually * render using a renderable format, without the override workaround it * wouldn't be possible to have a non-renderable surface in a fast clear * state so the hardware probably legitimately doesn't need to support * this case. At least on Gen9 this really does seem to cause problems. */ if (devinfo->gen >= 9 && brw_isl_format_for_mesa_format(mt->format) != brw->mesa_to_isl_render_format[mt->format]) return false; const mesa_format format = _mesa_get_render_format(ctx, mt->format); if (_mesa_is_format_integer_color(format)) { if (devinfo->gen >= 8) { perf_debug("Integer fast clear not enabled for (%s)", _mesa_get_format_name(format)); } return false; } for (int i = 0; i < 4; i++) { if (!_mesa_format_has_color_component(format, i)) { continue; } if (devinfo->gen < 9 && color->f[i] != 0.0f && color->f[i] != 1.0f) { return false; } } return true; }
static void intel_miptree_map_gtt(struct intel_context *intel, struct intel_mipmap_tree *mt, struct intel_miptree_map *map, unsigned int level, unsigned int slice) { unsigned int bw, bh; void *base; unsigned int image_x, image_y; int x = map->x; int y = map->y; /* For compressed formats, the stride is the number of bytes per * row of blocks. intel_miptree_get_image_offset() already does * the divide. */ _mesa_get_format_block_size(mt->format, &bw, &bh); assert(y % bh == 0); y /= bh; base = intel_miptree_map_raw(intel, mt) + mt->offset; if (base == NULL) map->ptr = NULL; else { /* Note that in the case of cube maps, the caller must have passed the * slice number referencing the face. */ intel_miptree_get_image_offset(mt, level, slice, &image_x, &image_y); x += image_x; y += image_y; map->stride = mt->region->pitch; map->ptr = base + y * map->stride + x * mt->cpp; } DBG("%s: %d,%d %dx%d from mt %p (%s) %d,%d = %p/%d\n", __func__, map->x, map->y, map->w, map->h, mt, _mesa_get_format_name(mt->format), x, y, map->ptr, map->stride); }
/** * Get texture image. Called by glGetTexImage. * * \param target texture target. * \param level image level. * \param format pixel data format for returned image. * \param type pixel data type for returned image. * \param bufSize size of the pixels data buffer. * \param pixels returned pixel data. */ void GLAPIENTRY _mesa_GetnTexImageARB( GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *pixels ) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); if (getteximage_error_check(ctx, target, level, format, type, bufSize, pixels)) { return; } if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { /* not an error, do nothing */ return; } texObj = _mesa_get_current_tex_object(ctx, target); texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (_mesa_is_zero_size_texture(texImage)) return; if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d," " dstFmt=0x%x, dstType=0x%x\n", texObj->Name, _mesa_get_format_name(texImage->TexFormat), texImage->Width, texImage->Height, format, type); } _mesa_lock_texture(ctx, texObj); { ctx->Driver.GetTexImage(ctx, format, type, pixels, texImage); } _mesa_unlock_texture(ctx, texObj); }
/** Implements glGetnCompressedTexImageARB, glGetCompressedTexImage, and * glGetCompressedTextureImage. * * texImage must be passed in because glGetCompressedTexImage must handle the * target GL_TEXTURE_CUBE_MAP. */ void _mesa_get_compressed_texture_image(struct gl_context *ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage, GLenum target, GLint level, GLsizei bufSize, GLvoid *pixels, bool dsa) { assert(texObj); assert(texImage); FLUSH_VERTICES(ctx, 0); if (getcompressedteximage_error_check(ctx, texImage, target, level, bufSize, pixels, dsa)) { return; } if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { /* not an error, do nothing */ return; } if (_mesa_is_zero_size_texture(texImage)) return; if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { _mesa_debug(ctx, "glGetCompressedTex%sImage(tex %u) format = %s, w=%d, h=%d\n", dsa ? "ture" : "", texObj->Name, _mesa_get_format_name(texImage->TexFormat), texImage->Width, texImage->Height); } _mesa_lock_texture(ctx, texObj); { ctx->Driver.GetCompressedTexImage(ctx, texImage, pixels); } _mesa_unlock_texture(ctx, texObj); }
uint32_t brw_depthbuffer_format(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb = ctx->DrawBuffer; struct intel_renderbuffer *drb = intel_get_renderbuffer(fb, BUFFER_DEPTH); struct intel_renderbuffer *srb; if (!drb && (srb = intel_get_renderbuffer(fb, BUFFER_STENCIL)) && !srb->mt->stencil_mt && (srb->Base.Format == MESA_FORMAT_S8_Z24 || srb->Base.Format == MESA_FORMAT_Z32_FLOAT_X24S8)) { drb = srb; } if (!drb) return BRW_DEPTHFORMAT_D32_FLOAT; switch (drb->mt->format) { case MESA_FORMAT_Z16: return BRW_DEPTHFORMAT_D16_UNORM; case MESA_FORMAT_Z32_FLOAT: return BRW_DEPTHFORMAT_D32_FLOAT; case MESA_FORMAT_X8_Z24: if (intel->gen >= 5) return BRW_DEPTHFORMAT_D24_UNORM_X8_UINT; else /* Gen4 doesn't support X8; use S8 instead. */ return BRW_DEPTHFORMAT_D24_UNORM_S8_UINT; case MESA_FORMAT_S8_Z24: return BRW_DEPTHFORMAT_D24_UNORM_S8_UINT; case MESA_FORMAT_Z32_FLOAT_X24S8: return BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT; default: _mesa_problem(ctx, "Unexpected depth format %s\n", _mesa_get_format_name(drb->Base.Format)); return BRW_DEPTHFORMAT_D16_UNORM; } }
void intel_miptree_unmap(struct intel_context *intel, struct intel_mipmap_tree *mt, unsigned int level, unsigned int slice) { struct intel_miptree_map *map = mt->level[level].slice[slice].map; if (!map) return; DBG("%s: mt %p (%s) level %d slice %d\n", __func__, mt, _mesa_get_format_name(mt->format), level, slice); if (map->mt) { intel_miptree_unmap_blit(intel, mt, map, level, slice); } else { intel_miptree_unmap_gtt(intel, mt, map, level, slice); } intel_miptree_release_map(mt, level, slice); }
/** * Called by Mesa when rendering to a texture is done. */ static void intel_finish_render_texture(struct gl_context * ctx, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_texture_object *tex_obj = att->Texture; struct gl_texture_image *image = tex_obj->Image[att->CubeMapFace][att->TextureLevel]; struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); DBG("Finish render %s texture tex=%u\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name); if (irb) irb->tex_image = NULL; /* Since we've (probably) rendered to the texture and will (likely) use * it in the texture domain later on in this batchbuffer, flush the * batch. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer like GEM does in the kernel. */ intel_batchbuffer_emit_mi_flush(intel); }
/** * Implements a rectangular block transfer (blit) of pixels between two * miptrees. * * Our blitter can operate on 1, 2, or 4-byte-per-pixel data, with generous, * but limited, pitches and sizes allowed. * * The src/dst coordinates are relative to the given level/slice of the * miptree. * * If @src_flip or @dst_flip is set, then the rectangle within that miptree * will be inverted (including scanline order) when copying. This is common * in GL when copying between window system and user-created * renderbuffers/textures. */ bool intel_miptree_blit(struct intel_context *intel, struct intel_mipmap_tree *src_mt, int src_level, int src_slice, uint32_t src_x, uint32_t src_y, bool src_flip, struct intel_mipmap_tree *dst_mt, int dst_level, int dst_slice, uint32_t dst_x, uint32_t dst_y, bool dst_flip, uint32_t width, uint32_t height, GLenum logicop) { /* No sRGB decode or encode is done by the hardware blitter, which is * consistent with what we want in the callers (glCopyTexSubImage(), * glBlitFramebuffer(), texture validation, etc.). */ gl_format src_format = _mesa_get_srgb_format_linear(src_mt->format); gl_format dst_format = _mesa_get_srgb_format_linear(dst_mt->format); /* The blitter doesn't support doing any format conversions. We do also * support blitting ARGB8888 to XRGB8888 (trivial, the values dropped into * the X channel don't matter), and XRGB8888 to ARGB8888 by setting the A * channel to 1.0 at the end. */ if (src_format != dst_format && ((src_format != MESA_FORMAT_ARGB8888 && src_format != MESA_FORMAT_XRGB8888) || (dst_format != MESA_FORMAT_ARGB8888 && dst_format != MESA_FORMAT_XRGB8888))) { perf_debug("%s: Can't use hardware blitter from %s to %s, " "falling back.\n", __FUNCTION__, _mesa_get_format_name(src_format), _mesa_get_format_name(dst_format)); return false; } /* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics * Data Size Limitations): * * The BLT engine is capable of transferring very large quantities of * graphics data. Any graphics data read from and written to the * destination is permitted to represent a number of pixels that * occupies up to 65,536 scan lines and up to 32,768 bytes per scan line * at the destination. The maximum number of pixels that may be * represented per scan line’s worth of graphics data depends on the * color depth. * * Furthermore, intelEmitCopyBlit (which is called below) uses a signed * 16-bit integer to represent buffer pitch, so it can only handle buffer * pitches < 32k. * * As a result of these two limitations, we can only use the blitter to do * this copy when the region's pitch is less than 32k. */ if (src_mt->region->pitch > 32768 || dst_mt->region->pitch > 32768) { perf_debug("Falling back due to >32k pitch\n"); return false; } if (src_flip) src_y = src_mt->level[src_level].height - src_y - height; if (dst_flip) dst_y = dst_mt->level[dst_level].height - dst_y - height; int src_pitch = src_mt->region->pitch; if (src_flip != dst_flip) src_pitch = -src_pitch; uint32_t src_image_x, src_image_y; intel_miptree_get_image_offset(src_mt, src_level, src_slice, &src_image_x, &src_image_y); src_x += src_image_x; src_y += src_image_y; uint32_t dst_image_x, dst_image_y; intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice, &dst_image_x, &dst_image_y); dst_x += dst_image_x; dst_y += dst_image_y; if (!intelEmitCopyBlit(intel, src_mt->cpp, src_pitch, src_mt->region->bo, src_mt->offset, src_mt->region->tiling, dst_mt->region->pitch, dst_mt->region->bo, dst_mt->offset, dst_mt->region->tiling, src_x, src_y, dst_x, dst_y, width, height, logicop)) { return false; } if (src_mt->format == MESA_FORMAT_XRGB8888 && dst_mt->format == MESA_FORMAT_ARGB8888) { intel_miptree_set_alpha_to_one(intel, dst_mt, dst_x, dst_y, width, height); } return true; }