1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (c) 2008-2009 VMware, Inc. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg/* 27848b8605Smrg * Authors: 28848b8605Smrg * Brian Paul 29848b8605Smrg */ 30848b8605Smrg 31848b8605Smrg/** 32848b8605Smrg * The GL texture image functions in teximage.c basically just do 33848b8605Smrg * error checking and data structure allocation. They in turn call 34848b8605Smrg * device driver functions which actually copy/convert/store the user's 35848b8605Smrg * texture image data. 36848b8605Smrg * 37848b8605Smrg * However, most device drivers will be able to use the fallback functions 38848b8605Smrg * in this file. That is, most drivers will have the following bit of 39848b8605Smrg * code: 40848b8605Smrg * ctx->Driver.TexImage = _mesa_store_teximage; 41848b8605Smrg * ctx->Driver.TexSubImage = _mesa_store_texsubimage; 42848b8605Smrg * etc... 43848b8605Smrg * 44848b8605Smrg * Texture image processing is actually kind of complicated. We have to do: 45848b8605Smrg * Format/type conversions 46848b8605Smrg * pixel unpacking 47848b8605Smrg * pixel transfer (scale, bais, lookup, etc) 48848b8605Smrg * 49848b8605Smrg * These functions can handle most everything, including processing full 50848b8605Smrg * images and sub-images. 51848b8605Smrg */ 52848b8605Smrg 53848b8605Smrg 54b8e80941Smrg#include "errors.h" 55848b8605Smrg#include "glheader.h" 56848b8605Smrg#include "bufferobj.h" 57848b8605Smrg#include "format_pack.h" 58848b8605Smrg#include "format_utils.h" 59848b8605Smrg#include "image.h" 60848b8605Smrg#include "macros.h" 61848b8605Smrg#include "mipmap.h" 62848b8605Smrg#include "mtypes.h" 63848b8605Smrg#include "pack.h" 64848b8605Smrg#include "pbo.h" 65848b8605Smrg#include "imports.h" 66848b8605Smrg#include "texcompress.h" 67848b8605Smrg#include "texcompress_fxt1.h" 68848b8605Smrg#include "texcompress_rgtc.h" 69848b8605Smrg#include "texcompress_s3tc.h" 70848b8605Smrg#include "texcompress_etc.h" 71848b8605Smrg#include "texcompress_bptc.h" 72848b8605Smrg#include "teximage.h" 73848b8605Smrg#include "texstore.h" 74848b8605Smrg#include "enums.h" 75848b8605Smrg#include "glformats.h" 76b8e80941Smrg#include "pixeltransfer.h" 77b8e80941Smrg#include "util/format_rgb9e5.h" 78b8e80941Smrg#include "util/format_r11g11b10f.h" 79848b8605Smrg 80848b8605Smrg 81848b8605Smrgenum { 82b8e80941Smrg ZERO = 4, 83848b8605Smrg ONE = 5 84848b8605Smrg}; 85848b8605Smrg 86848b8605Smrg 87848b8605Smrg/** 88848b8605Smrg * Texture image storage function. 89848b8605Smrg */ 90848b8605Smrgtypedef GLboolean (*StoreTexImageFunc)(TEXSTORE_PARAMS); 91848b8605Smrg 92848b8605Smrg 93848b8605Smrg/** 94b8e80941Smrg * Teximage storage routine for when a simple memcpy will do. 95b8e80941Smrg * No pixel transfer operations or special texel encodings allowed. 96b8e80941Smrg * 1D, 2D and 3D images supported. 97848b8605Smrg */ 98b8e80941Smrgvoid 99b8e80941Smrg_mesa_memcpy_texture(struct gl_context *ctx, 100b8e80941Smrg GLuint dimensions, 101b8e80941Smrg mesa_format dstFormat, 102b8e80941Smrg GLint dstRowStride, 103b8e80941Smrg GLubyte **dstSlices, 104848b8605Smrg GLint srcWidth, GLint srcHeight, GLint srcDepth, 105848b8605Smrg GLenum srcFormat, GLenum srcType, 106848b8605Smrg const GLvoid *srcAddr, 107848b8605Smrg const struct gl_pixelstore_attrib *srcPacking) 108848b8605Smrg{ 109848b8605Smrg const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, 110848b8605Smrg srcFormat, srcType); 111848b8605Smrg const GLint srcImageStride = _mesa_image_image_stride(srcPacking, 112848b8605Smrg srcWidth, srcHeight, srcFormat, srcType); 113848b8605Smrg const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions, 114848b8605Smrg srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); 115848b8605Smrg const GLuint texelBytes = _mesa_get_format_bytes(dstFormat); 116848b8605Smrg const GLint bytesPerRow = srcWidth * texelBytes; 117848b8605Smrg 118848b8605Smrg if (dstRowStride == srcRowStride && 119848b8605Smrg dstRowStride == bytesPerRow) { 120848b8605Smrg /* memcpy image by image */ 121848b8605Smrg GLint img; 122848b8605Smrg for (img = 0; img < srcDepth; img++) { 123848b8605Smrg GLubyte *dstImage = dstSlices[img]; 124848b8605Smrg memcpy(dstImage, srcImage, bytesPerRow * srcHeight); 125848b8605Smrg srcImage += srcImageStride; 126848b8605Smrg } 127848b8605Smrg } 128848b8605Smrg else { 129848b8605Smrg /* memcpy row by row */ 130848b8605Smrg GLint img, row; 131848b8605Smrg for (img = 0; img < srcDepth; img++) { 132848b8605Smrg const GLubyte *srcRow = srcImage; 133848b8605Smrg GLubyte *dstRow = dstSlices[img]; 134848b8605Smrg for (row = 0; row < srcHeight; row++) { 135848b8605Smrg memcpy(dstRow, srcRow, bytesPerRow); 136848b8605Smrg dstRow += dstRowStride; 137848b8605Smrg srcRow += srcRowStride; 138848b8605Smrg } 139848b8605Smrg srcImage += srcImageStride; 140848b8605Smrg } 141848b8605Smrg } 142848b8605Smrg} 143848b8605Smrg 144848b8605Smrg 145848b8605Smrg/** 146848b8605Smrg * Store a 32-bit integer or float depth component texture image. 147848b8605Smrg */ 148848b8605Smrgstatic GLboolean 149848b8605Smrg_mesa_texstore_z32(TEXSTORE_PARAMS) 150848b8605Smrg{ 151848b8605Smrg const GLuint depthScale = 0xffffffff; 152848b8605Smrg GLenum dstType; 153848b8605Smrg (void) dims; 154b8e80941Smrg assert(dstFormat == MESA_FORMAT_Z_UNORM32 || 155848b8605Smrg dstFormat == MESA_FORMAT_Z_FLOAT32); 156b8e80941Smrg assert(_mesa_get_format_bytes(dstFormat) == sizeof(GLuint)); 157848b8605Smrg 158848b8605Smrg if (dstFormat == MESA_FORMAT_Z_UNORM32) 159848b8605Smrg dstType = GL_UNSIGNED_INT; 160848b8605Smrg else 161848b8605Smrg dstType = GL_FLOAT; 162848b8605Smrg 163848b8605Smrg { 164848b8605Smrg /* general path */ 165848b8605Smrg GLint img, row; 166848b8605Smrg for (img = 0; img < srcDepth; img++) { 167848b8605Smrg GLubyte *dstRow = dstSlices[img]; 168848b8605Smrg for (row = 0; row < srcHeight; row++) { 169848b8605Smrg const GLvoid *src = _mesa_image_address(dims, srcPacking, 170848b8605Smrg srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 171848b8605Smrg _mesa_unpack_depth_span(ctx, srcWidth, 172848b8605Smrg dstType, dstRow, 173848b8605Smrg depthScale, srcType, src, srcPacking); 174848b8605Smrg dstRow += dstRowStride; 175848b8605Smrg } 176848b8605Smrg } 177848b8605Smrg } 178848b8605Smrg return GL_TRUE; 179848b8605Smrg} 180848b8605Smrg 181848b8605Smrg 182848b8605Smrg/** 183848b8605Smrg * Store a 24-bit integer depth component texture image. 184848b8605Smrg */ 185848b8605Smrgstatic GLboolean 186848b8605Smrg_mesa_texstore_x8_z24(TEXSTORE_PARAMS) 187848b8605Smrg{ 188848b8605Smrg const GLuint depthScale = 0xffffff; 189848b8605Smrg 190848b8605Smrg (void) dims; 191b8e80941Smrg assert(dstFormat == MESA_FORMAT_Z24_UNORM_X8_UINT); 192848b8605Smrg 193848b8605Smrg { 194848b8605Smrg /* general path */ 195848b8605Smrg GLint img, row; 196848b8605Smrg for (img = 0; img < srcDepth; img++) { 197848b8605Smrg GLubyte *dstRow = dstSlices[img]; 198848b8605Smrg for (row = 0; row < srcHeight; row++) { 199848b8605Smrg const GLvoid *src = _mesa_image_address(dims, srcPacking, 200848b8605Smrg srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 201848b8605Smrg _mesa_unpack_depth_span(ctx, srcWidth, 202848b8605Smrg GL_UNSIGNED_INT, (GLuint *) dstRow, 203848b8605Smrg depthScale, srcType, src, srcPacking); 204848b8605Smrg dstRow += dstRowStride; 205848b8605Smrg } 206848b8605Smrg } 207848b8605Smrg } 208848b8605Smrg return GL_TRUE; 209848b8605Smrg} 210848b8605Smrg 211848b8605Smrg 212848b8605Smrg/** 213848b8605Smrg * Store a 24-bit integer depth component texture image. 214848b8605Smrg */ 215848b8605Smrgstatic GLboolean 216848b8605Smrg_mesa_texstore_z24_x8(TEXSTORE_PARAMS) 217848b8605Smrg{ 218848b8605Smrg const GLuint depthScale = 0xffffff; 219848b8605Smrg 220848b8605Smrg (void) dims; 221b8e80941Smrg assert(dstFormat == MESA_FORMAT_X8_UINT_Z24_UNORM); 222848b8605Smrg 223848b8605Smrg { 224848b8605Smrg /* general path */ 225848b8605Smrg GLint img, row; 226848b8605Smrg for (img = 0; img < srcDepth; img++) { 227848b8605Smrg GLubyte *dstRow = dstSlices[img]; 228848b8605Smrg for (row = 0; row < srcHeight; row++) { 229848b8605Smrg const GLvoid *src = _mesa_image_address(dims, srcPacking, 230848b8605Smrg srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 231848b8605Smrg GLuint *dst = (GLuint *) dstRow; 232848b8605Smrg GLint i; 233848b8605Smrg _mesa_unpack_depth_span(ctx, srcWidth, 234848b8605Smrg GL_UNSIGNED_INT, dst, 235848b8605Smrg depthScale, srcType, src, srcPacking); 236848b8605Smrg for (i = 0; i < srcWidth; i++) 237848b8605Smrg dst[i] <<= 8; 238848b8605Smrg dstRow += dstRowStride; 239848b8605Smrg } 240848b8605Smrg } 241848b8605Smrg } 242848b8605Smrg return GL_TRUE; 243848b8605Smrg} 244848b8605Smrg 245848b8605Smrg 246848b8605Smrg/** 247848b8605Smrg * Store a 16-bit integer depth component texture image. 248848b8605Smrg */ 249848b8605Smrgstatic GLboolean 250848b8605Smrg_mesa_texstore_z16(TEXSTORE_PARAMS) 251848b8605Smrg{ 252848b8605Smrg const GLuint depthScale = 0xffff; 253848b8605Smrg (void) dims; 254b8e80941Smrg assert(dstFormat == MESA_FORMAT_Z_UNORM16); 255b8e80941Smrg assert(_mesa_get_format_bytes(dstFormat) == sizeof(GLushort)); 256848b8605Smrg 257848b8605Smrg { 258848b8605Smrg /* general path */ 259848b8605Smrg GLint img, row; 260848b8605Smrg for (img = 0; img < srcDepth; img++) { 261848b8605Smrg GLubyte *dstRow = dstSlices[img]; 262848b8605Smrg for (row = 0; row < srcHeight; row++) { 263848b8605Smrg const GLvoid *src = _mesa_image_address(dims, srcPacking, 264848b8605Smrg srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 265848b8605Smrg GLushort *dst16 = (GLushort *) dstRow; 266848b8605Smrg _mesa_unpack_depth_span(ctx, srcWidth, 267848b8605Smrg GL_UNSIGNED_SHORT, dst16, depthScale, 268848b8605Smrg srcType, src, srcPacking); 269848b8605Smrg dstRow += dstRowStride; 270848b8605Smrg } 271848b8605Smrg } 272848b8605Smrg } 273848b8605Smrg return GL_TRUE; 274848b8605Smrg} 275848b8605Smrg 276848b8605Smrg 277848b8605Smrg/** 278848b8605Smrg * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV. 279848b8605Smrg */ 280848b8605Smrgstatic GLboolean 281848b8605Smrg_mesa_texstore_ycbcr(TEXSTORE_PARAMS) 282848b8605Smrg{ 283848b8605Smrg const GLboolean littleEndian = _mesa_little_endian(); 284848b8605Smrg 285848b8605Smrg (void) ctx; (void) dims; (void) baseInternalFormat; 286848b8605Smrg 287b8e80941Smrg assert((dstFormat == MESA_FORMAT_YCBCR) || 288848b8605Smrg (dstFormat == MESA_FORMAT_YCBCR_REV)); 289b8e80941Smrg assert(_mesa_get_format_bytes(dstFormat) == 2); 290b8e80941Smrg assert(ctx->Extensions.MESA_ycbcr_texture); 291b8e80941Smrg assert(srcFormat == GL_YCBCR_MESA); 292b8e80941Smrg assert((srcType == GL_UNSIGNED_SHORT_8_8_MESA) || 293848b8605Smrg (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA)); 294b8e80941Smrg assert(baseInternalFormat == GL_YCBCR_MESA); 295848b8605Smrg 296848b8605Smrg /* always just memcpy since no pixel transfer ops apply */ 297b8e80941Smrg _mesa_memcpy_texture(ctx, dims, 298b8e80941Smrg dstFormat, 299b8e80941Smrg dstRowStride, dstSlices, 300b8e80941Smrg srcWidth, srcHeight, srcDepth, srcFormat, srcType, 301b8e80941Smrg srcAddr, srcPacking); 302848b8605Smrg 303848b8605Smrg /* Check if we need byte swapping */ 304848b8605Smrg /* XXX the logic here _might_ be wrong */ 305848b8605Smrg if (srcPacking->SwapBytes ^ 306848b8605Smrg (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^ 307848b8605Smrg (dstFormat == MESA_FORMAT_YCBCR_REV) ^ 308848b8605Smrg !littleEndian) { 309848b8605Smrg GLint img, row; 310848b8605Smrg for (img = 0; img < srcDepth; img++) { 311848b8605Smrg GLubyte *dstRow = dstSlices[img]; 312848b8605Smrg for (row = 0; row < srcHeight; row++) { 313848b8605Smrg _mesa_swap2((GLushort *) dstRow, srcWidth); 314848b8605Smrg dstRow += dstRowStride; 315848b8605Smrg } 316848b8605Smrg } 317848b8605Smrg } 318848b8605Smrg return GL_TRUE; 319848b8605Smrg} 320848b8605Smrg 321848b8605Smrg 322848b8605Smrg/** 323848b8605Smrg * Store a combined depth/stencil texture image. 324848b8605Smrg */ 325848b8605Smrgstatic GLboolean 326848b8605Smrg_mesa_texstore_z24_s8(TEXSTORE_PARAMS) 327848b8605Smrg{ 328848b8605Smrg const GLuint depthScale = 0xffffff; 329848b8605Smrg const GLint srcRowStride 330848b8605Smrg = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); 331848b8605Smrg GLint img, row; 332848b8605Smrg GLuint *depth = malloc(srcWidth * sizeof(GLuint)); 333848b8605Smrg GLubyte *stencil = malloc(srcWidth * sizeof(GLubyte)); 334848b8605Smrg 335b8e80941Smrg assert(dstFormat == MESA_FORMAT_S8_UINT_Z24_UNORM); 336b8e80941Smrg assert(srcFormat == GL_DEPTH_STENCIL_EXT || 337848b8605Smrg srcFormat == GL_DEPTH_COMPONENT || 338848b8605Smrg srcFormat == GL_STENCIL_INDEX); 339b8e80941Smrg assert(srcFormat != GL_DEPTH_STENCIL_EXT || 340848b8605Smrg srcType == GL_UNSIGNED_INT_24_8_EXT || 341848b8605Smrg srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); 342848b8605Smrg 343848b8605Smrg if (!depth || !stencil) { 344848b8605Smrg free(depth); 345848b8605Smrg free(stencil); 346848b8605Smrg return GL_FALSE; 347848b8605Smrg } 348848b8605Smrg 349848b8605Smrg /* In case we only upload depth we need to preserve the stencil */ 350848b8605Smrg for (img = 0; img < srcDepth; img++) { 351848b8605Smrg GLuint *dstRow = (GLuint *) dstSlices[img]; 352848b8605Smrg const GLubyte *src 353848b8605Smrg = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, 354848b8605Smrg srcWidth, srcHeight, 355848b8605Smrg srcFormat, srcType, 356848b8605Smrg img, 0, 0); 357848b8605Smrg for (row = 0; row < srcHeight; row++) { 358848b8605Smrg GLint i; 359848b8605Smrg GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE; 360848b8605Smrg 361848b8605Smrg if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */ 362848b8605Smrg keepstencil = GL_TRUE; 363848b8605Smrg } 364848b8605Smrg else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */ 365848b8605Smrg keepdepth = GL_TRUE; 366848b8605Smrg } 367848b8605Smrg 368848b8605Smrg if (keepdepth == GL_FALSE) 369848b8605Smrg /* the 24 depth bits will be in the low position: */ 370848b8605Smrg _mesa_unpack_depth_span(ctx, srcWidth, 371848b8605Smrg GL_UNSIGNED_INT, /* dst type */ 372848b8605Smrg keepstencil ? depth : dstRow, /* dst addr */ 373848b8605Smrg depthScale, 374848b8605Smrg srcType, src, srcPacking); 375848b8605Smrg 376848b8605Smrg if (keepstencil == GL_FALSE) 377848b8605Smrg /* get the 8-bit stencil values */ 378848b8605Smrg _mesa_unpack_stencil_span(ctx, srcWidth, 379848b8605Smrg GL_UNSIGNED_BYTE, /* dst type */ 380848b8605Smrg stencil, /* dst addr */ 381848b8605Smrg srcType, src, srcPacking, 382848b8605Smrg ctx->_ImageTransferState); 383848b8605Smrg 384848b8605Smrg for (i = 0; i < srcWidth; i++) { 385848b8605Smrg if (keepstencil) 386848b8605Smrg dstRow[i] = depth[i] << 8 | (dstRow[i] & 0x000000FF); 387848b8605Smrg else 388848b8605Smrg dstRow[i] = (dstRow[i] & 0xFFFFFF00) | (stencil[i] & 0xFF); 389848b8605Smrg } 390848b8605Smrg src += srcRowStride; 391848b8605Smrg dstRow += dstRowStride / sizeof(GLuint); 392848b8605Smrg } 393848b8605Smrg } 394848b8605Smrg 395848b8605Smrg free(depth); 396848b8605Smrg free(stencil); 397848b8605Smrg return GL_TRUE; 398848b8605Smrg} 399848b8605Smrg 400848b8605Smrg 401848b8605Smrg/** 402848b8605Smrg * Store a combined depth/stencil texture image. 403848b8605Smrg */ 404848b8605Smrgstatic GLboolean 405848b8605Smrg_mesa_texstore_s8_z24(TEXSTORE_PARAMS) 406848b8605Smrg{ 407848b8605Smrg const GLuint depthScale = 0xffffff; 408848b8605Smrg const GLint srcRowStride 409848b8605Smrg = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); 410848b8605Smrg GLint img, row; 411848b8605Smrg GLuint *depth; 412848b8605Smrg GLubyte *stencil; 413848b8605Smrg 414b8e80941Smrg assert(dstFormat == MESA_FORMAT_Z24_UNORM_S8_UINT); 415b8e80941Smrg assert(srcFormat == GL_DEPTH_STENCIL_EXT || 416848b8605Smrg srcFormat == GL_DEPTH_COMPONENT || 417848b8605Smrg srcFormat == GL_STENCIL_INDEX); 418b8e80941Smrg assert(srcFormat != GL_DEPTH_STENCIL_EXT || 419848b8605Smrg srcType == GL_UNSIGNED_INT_24_8_EXT || 420848b8605Smrg srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); 421848b8605Smrg 422848b8605Smrg depth = malloc(srcWidth * sizeof(GLuint)); 423848b8605Smrg stencil = malloc(srcWidth * sizeof(GLubyte)); 424848b8605Smrg 425848b8605Smrg if (!depth || !stencil) { 426848b8605Smrg free(depth); 427848b8605Smrg free(stencil); 428848b8605Smrg return GL_FALSE; 429848b8605Smrg } 430848b8605Smrg 431848b8605Smrg for (img = 0; img < srcDepth; img++) { 432848b8605Smrg GLuint *dstRow = (GLuint *) dstSlices[img]; 433848b8605Smrg const GLubyte *src 434b8e80941Smrg = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, 435b8e80941Smrg srcWidth, srcHeight, 436b8e80941Smrg srcFormat, srcType, 437b8e80941Smrg img, 0, 0); 438848b8605Smrg for (row = 0; row < srcHeight; row++) { 439b8e80941Smrg GLint i; 440b8e80941Smrg GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE; 441b8e80941Smrg 442b8e80941Smrg if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */ 443b8e80941Smrg keepstencil = GL_TRUE; 444b8e80941Smrg } 445848b8605Smrg else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */ 446b8e80941Smrg keepdepth = GL_TRUE; 447b8e80941Smrg } 448b8e80941Smrg 449b8e80941Smrg if (keepdepth == GL_FALSE) 450b8e80941Smrg /* the 24 depth bits will be in the low position: */ 451b8e80941Smrg _mesa_unpack_depth_span(ctx, srcWidth, 452b8e80941Smrg GL_UNSIGNED_INT, /* dst type */ 453b8e80941Smrg keepstencil ? depth : dstRow, /* dst addr */ 454b8e80941Smrg depthScale, 455b8e80941Smrg srcType, src, srcPacking); 456b8e80941Smrg 457b8e80941Smrg if (keepstencil == GL_FALSE) 458b8e80941Smrg /* get the 8-bit stencil values */ 459b8e80941Smrg _mesa_unpack_stencil_span(ctx, srcWidth, 460b8e80941Smrg GL_UNSIGNED_BYTE, /* dst type */ 461b8e80941Smrg stencil, /* dst addr */ 462b8e80941Smrg srcType, src, srcPacking, 463b8e80941Smrg ctx->_ImageTransferState); 464b8e80941Smrg 465b8e80941Smrg /* merge stencil values into depth values */ 466b8e80941Smrg for (i = 0; i < srcWidth; i++) { 467b8e80941Smrg if (keepstencil) 468b8e80941Smrg dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000); 469b8e80941Smrg else 470b8e80941Smrg dstRow[i] = (dstRow[i] & 0xFFFFFF) | (stencil[i] << 24); 471b8e80941Smrg 472b8e80941Smrg } 473b8e80941Smrg src += srcRowStride; 474b8e80941Smrg dstRow += dstRowStride / sizeof(GLuint); 475848b8605Smrg } 476848b8605Smrg } 477848b8605Smrg 478848b8605Smrg free(depth); 479848b8605Smrg free(stencil); 480848b8605Smrg 481848b8605Smrg return GL_TRUE; 482848b8605Smrg} 483848b8605Smrg 484848b8605Smrg 485848b8605Smrg/** 486848b8605Smrg * Store simple 8-bit/value stencil texture data. 487848b8605Smrg */ 488848b8605Smrgstatic GLboolean 489848b8605Smrg_mesa_texstore_s8(TEXSTORE_PARAMS) 490848b8605Smrg{ 491b8e80941Smrg assert(dstFormat == MESA_FORMAT_S_UINT8); 492b8e80941Smrg assert(srcFormat == GL_STENCIL_INDEX); 493848b8605Smrg 494848b8605Smrg { 495848b8605Smrg const GLint srcRowStride 496b8e80941Smrg = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); 497848b8605Smrg GLint img, row; 498848b8605Smrg GLubyte *stencil = malloc(srcWidth * sizeof(GLubyte)); 499848b8605Smrg 500848b8605Smrg if (!stencil) 501848b8605Smrg return GL_FALSE; 502848b8605Smrg 503848b8605Smrg for (img = 0; img < srcDepth; img++) { 504848b8605Smrg GLubyte *dstRow = dstSlices[img]; 505848b8605Smrg const GLubyte *src 506848b8605Smrg = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, 507848b8605Smrg srcWidth, srcHeight, 508848b8605Smrg srcFormat, srcType, 509848b8605Smrg img, 0, 0); 510848b8605Smrg for (row = 0; row < srcHeight; row++) { 511848b8605Smrg GLint i; 512848b8605Smrg 513848b8605Smrg /* get the 8-bit stencil values */ 514848b8605Smrg _mesa_unpack_stencil_span(ctx, srcWidth, 515848b8605Smrg GL_UNSIGNED_BYTE, /* dst type */ 516848b8605Smrg stencil, /* dst addr */ 517848b8605Smrg srcType, src, srcPacking, 518848b8605Smrg ctx->_ImageTransferState); 519848b8605Smrg /* merge stencil values into depth values */ 520848b8605Smrg for (i = 0; i < srcWidth; i++) 521848b8605Smrg dstRow[i] = stencil[i]; 522848b8605Smrg 523848b8605Smrg src += srcRowStride; 524848b8605Smrg dstRow += dstRowStride / sizeof(GLubyte); 525848b8605Smrg } 526848b8605Smrg } 527848b8605Smrg 528848b8605Smrg free(stencil); 529848b8605Smrg } 530848b8605Smrg 531848b8605Smrg return GL_TRUE; 532848b8605Smrg} 533848b8605Smrg 534848b8605Smrg 535848b8605Smrgstatic GLboolean 536848b8605Smrg_mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS) 537848b8605Smrg{ 538848b8605Smrg GLint img, row; 539848b8605Smrg const GLint srcRowStride 540848b8605Smrg = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) 541848b8605Smrg / sizeof(uint64_t); 542848b8605Smrg 543b8e80941Smrg assert(dstFormat == MESA_FORMAT_Z32_FLOAT_S8X24_UINT); 544b8e80941Smrg assert(srcFormat == GL_DEPTH_STENCIL || 545848b8605Smrg srcFormat == GL_DEPTH_COMPONENT || 546848b8605Smrg srcFormat == GL_STENCIL_INDEX); 547b8e80941Smrg assert(srcFormat != GL_DEPTH_STENCIL || 548848b8605Smrg srcType == GL_UNSIGNED_INT_24_8 || 549848b8605Smrg srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); 550848b8605Smrg 551848b8605Smrg /* In case we only upload depth we need to preserve the stencil */ 552848b8605Smrg for (img = 0; img < srcDepth; img++) { 553848b8605Smrg uint64_t *dstRow = (uint64_t *) dstSlices[img]; 554848b8605Smrg const uint64_t *src 555848b8605Smrg = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr, 556848b8605Smrg srcWidth, srcHeight, 557848b8605Smrg srcFormat, srcType, 558848b8605Smrg img, 0, 0); 559848b8605Smrg for (row = 0; row < srcHeight; row++) { 560848b8605Smrg /* The unpack functions with: 561848b8605Smrg * dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV 562848b8605Smrg * only write their own dword, so the other dword (stencil 563848b8605Smrg * or depth) is preserved. */ 564848b8605Smrg if (srcFormat != GL_STENCIL_INDEX) 565848b8605Smrg _mesa_unpack_depth_span(ctx, srcWidth, 566848b8605Smrg GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ 567848b8605Smrg dstRow, /* dst addr */ 568848b8605Smrg ~0U, srcType, src, srcPacking); 569848b8605Smrg 570848b8605Smrg if (srcFormat != GL_DEPTH_COMPONENT) 571848b8605Smrg _mesa_unpack_stencil_span(ctx, srcWidth, 572848b8605Smrg GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ 573848b8605Smrg dstRow, /* dst addr */ 574848b8605Smrg srcType, src, srcPacking, 575848b8605Smrg ctx->_ImageTransferState); 576848b8605Smrg 577848b8605Smrg src += srcRowStride; 578848b8605Smrg dstRow += dstRowStride / sizeof(uint64_t); 579848b8605Smrg } 580848b8605Smrg } 581848b8605Smrg return GL_TRUE; 582848b8605Smrg} 583848b8605Smrg 584848b8605Smrgstatic GLboolean 585848b8605Smrgtexstore_depth_stencil(TEXSTORE_PARAMS) 586848b8605Smrg{ 587848b8605Smrg static StoreTexImageFunc table[MESA_FORMAT_COUNT]; 588848b8605Smrg static GLboolean initialized = GL_FALSE; 589848b8605Smrg 590848b8605Smrg if (!initialized) { 591848b8605Smrg memset(table, 0, sizeof table); 592848b8605Smrg 593848b8605Smrg table[MESA_FORMAT_S8_UINT_Z24_UNORM] = _mesa_texstore_z24_s8; 594848b8605Smrg table[MESA_FORMAT_Z24_UNORM_S8_UINT] = _mesa_texstore_s8_z24; 595848b8605Smrg table[MESA_FORMAT_Z_UNORM16] = _mesa_texstore_z16; 596848b8605Smrg table[MESA_FORMAT_Z24_UNORM_X8_UINT] = _mesa_texstore_x8_z24; 597848b8605Smrg table[MESA_FORMAT_X8_UINT_Z24_UNORM] = _mesa_texstore_z24_x8; 598848b8605Smrg table[MESA_FORMAT_Z_UNORM32] = _mesa_texstore_z32; 599848b8605Smrg table[MESA_FORMAT_S_UINT8] = _mesa_texstore_s8; 600848b8605Smrg table[MESA_FORMAT_Z_FLOAT32] = _mesa_texstore_z32; 601848b8605Smrg table[MESA_FORMAT_Z32_FLOAT_S8X24_UINT] = _mesa_texstore_z32f_x24s8; 602848b8605Smrg 603848b8605Smrg initialized = GL_TRUE; 604848b8605Smrg } 605848b8605Smrg 606b8e80941Smrg assert(table[dstFormat]); 607848b8605Smrg return table[dstFormat](ctx, dims, baseInternalFormat, 608848b8605Smrg dstFormat, dstRowStride, dstSlices, 609848b8605Smrg srcWidth, srcHeight, srcDepth, 610848b8605Smrg srcFormat, srcType, srcAddr, srcPacking); 611848b8605Smrg} 612848b8605Smrg 613848b8605Smrgstatic GLboolean 614848b8605Smrgtexstore_compressed(TEXSTORE_PARAMS) 615848b8605Smrg{ 616848b8605Smrg static StoreTexImageFunc table[MESA_FORMAT_COUNT]; 617848b8605Smrg static GLboolean initialized = GL_FALSE; 618848b8605Smrg 619848b8605Smrg if (!initialized) { 620848b8605Smrg memset(table, 0, sizeof table); 621848b8605Smrg 622848b8605Smrg table[MESA_FORMAT_SRGB_DXT1] = _mesa_texstore_rgb_dxt1; 623848b8605Smrg table[MESA_FORMAT_SRGBA_DXT1] = _mesa_texstore_rgba_dxt1; 624848b8605Smrg table[MESA_FORMAT_SRGBA_DXT3] = _mesa_texstore_rgba_dxt3; 625848b8605Smrg table[MESA_FORMAT_SRGBA_DXT5] = _mesa_texstore_rgba_dxt5; 626848b8605Smrg table[MESA_FORMAT_RGB_FXT1] = _mesa_texstore_rgb_fxt1; 627848b8605Smrg table[MESA_FORMAT_RGBA_FXT1] = _mesa_texstore_rgba_fxt1; 628848b8605Smrg table[MESA_FORMAT_RGB_DXT1] = _mesa_texstore_rgb_dxt1; 629848b8605Smrg table[MESA_FORMAT_RGBA_DXT1] = _mesa_texstore_rgba_dxt1; 630848b8605Smrg table[MESA_FORMAT_RGBA_DXT3] = _mesa_texstore_rgba_dxt3; 631848b8605Smrg table[MESA_FORMAT_RGBA_DXT5] = _mesa_texstore_rgba_dxt5; 632848b8605Smrg table[MESA_FORMAT_R_RGTC1_UNORM] = _mesa_texstore_red_rgtc1; 633848b8605Smrg table[MESA_FORMAT_R_RGTC1_SNORM] = _mesa_texstore_signed_red_rgtc1; 634848b8605Smrg table[MESA_FORMAT_RG_RGTC2_UNORM] = _mesa_texstore_rg_rgtc2; 635848b8605Smrg table[MESA_FORMAT_RG_RGTC2_SNORM] = _mesa_texstore_signed_rg_rgtc2; 636848b8605Smrg table[MESA_FORMAT_L_LATC1_UNORM] = _mesa_texstore_red_rgtc1; 637848b8605Smrg table[MESA_FORMAT_L_LATC1_SNORM] = _mesa_texstore_signed_red_rgtc1; 638848b8605Smrg table[MESA_FORMAT_LA_LATC2_UNORM] = _mesa_texstore_rg_rgtc2; 639848b8605Smrg table[MESA_FORMAT_LA_LATC2_SNORM] = _mesa_texstore_signed_rg_rgtc2; 640848b8605Smrg table[MESA_FORMAT_ETC1_RGB8] = _mesa_texstore_etc1_rgb8; 641848b8605Smrg table[MESA_FORMAT_ETC2_RGB8] = _mesa_texstore_etc2_rgb8; 642848b8605Smrg table[MESA_FORMAT_ETC2_SRGB8] = _mesa_texstore_etc2_srgb8; 643848b8605Smrg table[MESA_FORMAT_ETC2_RGBA8_EAC] = _mesa_texstore_etc2_rgba8_eac; 644848b8605Smrg table[MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC] = _mesa_texstore_etc2_srgb8_alpha8_eac; 645848b8605Smrg table[MESA_FORMAT_ETC2_R11_EAC] = _mesa_texstore_etc2_r11_eac; 646848b8605Smrg table[MESA_FORMAT_ETC2_RG11_EAC] = _mesa_texstore_etc2_rg11_eac; 647848b8605Smrg table[MESA_FORMAT_ETC2_SIGNED_R11_EAC] = _mesa_texstore_etc2_signed_r11_eac; 648848b8605Smrg table[MESA_FORMAT_ETC2_SIGNED_RG11_EAC] = _mesa_texstore_etc2_signed_rg11_eac; 649848b8605Smrg table[MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1] = 650848b8605Smrg _mesa_texstore_etc2_rgb8_punchthrough_alpha1; 651848b8605Smrg table[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] = 652848b8605Smrg _mesa_texstore_etc2_srgb8_punchthrough_alpha1; 653848b8605Smrg 654848b8605Smrg table[MESA_FORMAT_BPTC_RGBA_UNORM] = 655848b8605Smrg _mesa_texstore_bptc_rgba_unorm; 656848b8605Smrg table[MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM] = 657848b8605Smrg _mesa_texstore_bptc_rgba_unorm; 658848b8605Smrg table[MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT] = 659848b8605Smrg _mesa_texstore_bptc_rgb_signed_float; 660848b8605Smrg table[MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT] = 661848b8605Smrg _mesa_texstore_bptc_rgb_unsigned_float; 662848b8605Smrg 663848b8605Smrg initialized = GL_TRUE; 664848b8605Smrg } 665848b8605Smrg 666b8e80941Smrg assert(table[dstFormat]); 667848b8605Smrg return table[dstFormat](ctx, dims, baseInternalFormat, 668848b8605Smrg dstFormat, dstRowStride, dstSlices, 669848b8605Smrg srcWidth, srcHeight, srcDepth, 670848b8605Smrg srcFormat, srcType, srcAddr, srcPacking); 671848b8605Smrg} 672848b8605Smrg 673848b8605Smrgstatic GLboolean 674b8e80941Smrgtexstore_rgba(TEXSTORE_PARAMS) 675848b8605Smrg{ 676b8e80941Smrg void *tempImage = NULL; 677b8e80941Smrg int img; 678b8e80941Smrg GLubyte *src, *dst; 679b8e80941Smrg uint8_t rebaseSwizzle[4]; 680b8e80941Smrg bool transferOpsDone = false; 681b8e80941Smrg 682b8e80941Smrg /* We have to handle MESA_FORMAT_YCBCR manually because it is a special case 683b8e80941Smrg * and _mesa_format_convert does not support it. In this case the we only 684b8e80941Smrg * allow conversions between YCBCR formats and it is mostly a memcpy. 685b8e80941Smrg */ 686b8e80941Smrg if (dstFormat == MESA_FORMAT_YCBCR || dstFormat == MESA_FORMAT_YCBCR_REV) { 687b8e80941Smrg return _mesa_texstore_ycbcr(ctx, dims, baseInternalFormat, 688b8e80941Smrg dstFormat, dstRowStride, dstSlices, 689b8e80941Smrg srcWidth, srcHeight, srcDepth, 690b8e80941Smrg srcFormat, srcType, srcAddr, 691b8e80941Smrg srcPacking); 692848b8605Smrg } 693848b8605Smrg 694b8e80941Smrg /* We have to deal with GL_COLOR_INDEX manually because 695b8e80941Smrg * _mesa_format_convert does not handle this format. So what we do here is 696b8e80941Smrg * convert it to RGBA ubyte first and then convert from that to dst as usual. 697b8e80941Smrg */ 698b8e80941Smrg if (srcFormat == GL_COLOR_INDEX) { 699b8e80941Smrg /* Notice that this will already handle byte swapping if necessary */ 700b8e80941Smrg tempImage = 701b8e80941Smrg _mesa_unpack_color_index_to_rgba_ubyte(ctx, dims, 702b8e80941Smrg srcAddr, srcFormat, srcType, 703b8e80941Smrg srcWidth, srcHeight, srcDepth, 704b8e80941Smrg srcPacking, 705b8e80941Smrg ctx->_ImageTransferState); 706b8e80941Smrg if (!tempImage) 707b8e80941Smrg return GL_FALSE; 708848b8605Smrg 709b8e80941Smrg /* _mesa_unpack_color_index_to_rgba_ubyte has handled transferops 710b8e80941Smrg * if needed. 711b8e80941Smrg */ 712b8e80941Smrg transferOpsDone = true; 713848b8605Smrg 714b8e80941Smrg /* Now we only have to adjust our src info for a conversion from 715b8e80941Smrg * the RGBA ubyte and then we continue as usual. 716b8e80941Smrg */ 717b8e80941Smrg srcAddr = tempImage; 718b8e80941Smrg srcFormat = GL_RGBA; 719b8e80941Smrg srcType = GL_UNSIGNED_BYTE; 720b8e80941Smrg } else if (srcPacking->SwapBytes) { 721b8e80941Smrg /* We have to handle byte-swapping scenarios before calling 722b8e80941Smrg * _mesa_format_convert 723b8e80941Smrg */ 724b8e80941Smrg GLint swapSize = _mesa_sizeof_packed_type(srcType); 725b8e80941Smrg if (swapSize == 2 || swapSize == 4) { 726b8e80941Smrg int imageStride = _mesa_image_image_stride(srcPacking, srcWidth, 727b8e80941Smrg srcHeight, srcFormat, 728b8e80941Smrg srcType); 729b8e80941Smrg int bufferSize = imageStride * srcDepth; 730b8e80941Smrg int layer; 731b8e80941Smrg const uint8_t *src; 732b8e80941Smrg uint8_t *dst; 733b8e80941Smrg 734b8e80941Smrg tempImage = malloc(bufferSize); 735b8e80941Smrg if (!tempImage) 736b8e80941Smrg return GL_FALSE; 737b8e80941Smrg src = srcAddr; 738b8e80941Smrg dst = tempImage; 739b8e80941Smrg for (layer = 0; layer < srcDepth; layer++) { 740b8e80941Smrg _mesa_swap_bytes_2d_image(srcFormat, srcType, 741b8e80941Smrg srcPacking, 742b8e80941Smrg srcWidth, srcHeight, 743b8e80941Smrg dst, src); 744b8e80941Smrg src += imageStride; 745b8e80941Smrg dst += imageStride; 746848b8605Smrg } 747b8e80941Smrg srcAddr = tempImage; 748848b8605Smrg } 749848b8605Smrg } 750848b8605Smrg 751b8e80941Smrg int srcRowStride = 752848b8605Smrg _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); 753848b8605Smrg 754b8e80941Smrg uint32_t srcMesaFormat = 755b8e80941Smrg _mesa_format_from_format_and_type(srcFormat, srcType); 756848b8605Smrg 757848b8605Smrg dstFormat = _mesa_get_srgb_format_linear(dstFormat); 758848b8605Smrg 759b8e80941Smrg /* If we have transferOps then we need to convert to RGBA float first, 760b8e80941Smrg then apply transferOps, then do the conversion to dst 761b8e80941Smrg */ 762b8e80941Smrg void *tempRGBA = NULL; 763b8e80941Smrg if (!transferOpsDone && 764b8e80941Smrg _mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) { 765b8e80941Smrg /* Allocate RGBA float image */ 766b8e80941Smrg int elementCount = srcWidth * srcHeight * srcDepth; 767b8e80941Smrg tempRGBA = malloc(4 * elementCount * sizeof(float)); 768b8e80941Smrg if (!tempRGBA) { 769b8e80941Smrg free(tempImage); 770b8e80941Smrg return GL_FALSE; 771848b8605Smrg } 772848b8605Smrg 773b8e80941Smrg /* Convert from src to RGBA float */ 774b8e80941Smrg src = (GLubyte *) srcAddr; 775b8e80941Smrg dst = (GLubyte *) tempRGBA; 776b8e80941Smrg for (img = 0; img < srcDepth; img++) { 777b8e80941Smrg _mesa_format_convert(dst, RGBA32_FLOAT, 4 * srcWidth * sizeof(float), 778b8e80941Smrg src, srcMesaFormat, srcRowStride, 779b8e80941Smrg srcWidth, srcHeight, NULL); 780b8e80941Smrg src += srcHeight * srcRowStride; 781b8e80941Smrg dst += srcHeight * 4 * srcWidth * sizeof(float); 782848b8605Smrg } 783848b8605Smrg 784b8e80941Smrg /* Apply transferOps */ 785b8e80941Smrg _mesa_apply_rgba_transfer_ops(ctx, ctx->_ImageTransferState, elementCount, 786b8e80941Smrg (float(*)[4]) tempRGBA); 787848b8605Smrg 788b8e80941Smrg /* Now we have to adjust our src info for a conversion from 789b8e80941Smrg * the RGBA float image and then we continue as usual. 790b8e80941Smrg */ 791b8e80941Smrg srcAddr = tempRGBA; 792b8e80941Smrg srcFormat = GL_RGBA; 793b8e80941Smrg srcType = GL_FLOAT; 794b8e80941Smrg srcRowStride = srcWidth * 4 * sizeof(float); 795b8e80941Smrg srcMesaFormat = RGBA32_FLOAT; 796b8e80941Smrg srcPacking = &ctx->DefaultPacking; 797848b8605Smrg } 798848b8605Smrg 799b8e80941Smrg src = (GLubyte *) 800b8e80941Smrg _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, 801b8e80941Smrg srcFormat, srcType, 0, 0, 0); 802b8e80941Smrg 803b8e80941Smrg bool needRebase; 804b8e80941Smrg if (_mesa_get_format_base_format(dstFormat) != baseInternalFormat) { 805b8e80941Smrg needRebase = 806b8e80941Smrg _mesa_compute_rgba2base2rgba_component_mapping(baseInternalFormat, 807b8e80941Smrg rebaseSwizzle); 808848b8605Smrg } else { 809b8e80941Smrg needRebase = false; 810848b8605Smrg } 811848b8605Smrg 812848b8605Smrg for (img = 0; img < srcDepth; img++) { 813b8e80941Smrg _mesa_format_convert(dstSlices[img], dstFormat, dstRowStride, 814b8e80941Smrg src, srcMesaFormat, srcRowStride, 815b8e80941Smrg srcWidth, srcHeight, 816b8e80941Smrg needRebase ? rebaseSwizzle : NULL); 817b8e80941Smrg src += srcHeight * srcRowStride; 818848b8605Smrg } 819848b8605Smrg 820b8e80941Smrg free(tempImage); 821b8e80941Smrg free(tempRGBA); 822848b8605Smrg 823b8e80941Smrg return GL_TRUE; 824848b8605Smrg} 825848b8605Smrg 826848b8605SmrgGLboolean 827848b8605Smrg_mesa_texstore_needs_transfer_ops(struct gl_context *ctx, 828848b8605Smrg GLenum baseInternalFormat, 829848b8605Smrg mesa_format dstFormat) 830848b8605Smrg{ 831848b8605Smrg GLenum dstType; 832848b8605Smrg 833848b8605Smrg /* There are different rules depending on the base format. */ 834848b8605Smrg switch (baseInternalFormat) { 835848b8605Smrg case GL_DEPTH_COMPONENT: 836848b8605Smrg case GL_DEPTH_STENCIL: 837848b8605Smrg return ctx->Pixel.DepthScale != 1.0f || 838848b8605Smrg ctx->Pixel.DepthBias != 0.0f; 839848b8605Smrg 840848b8605Smrg case GL_STENCIL_INDEX: 841848b8605Smrg return GL_FALSE; 842848b8605Smrg 843848b8605Smrg default: 844848b8605Smrg /* Color formats. 845848b8605Smrg * Pixel transfer ops (scale, bias, table lookup) do not apply 846848b8605Smrg * to integer formats. 847848b8605Smrg */ 848848b8605Smrg dstType = _mesa_get_format_datatype(dstFormat); 849848b8605Smrg 850848b8605Smrg return dstType != GL_INT && dstType != GL_UNSIGNED_INT && 851848b8605Smrg ctx->_ImageTransferState; 852848b8605Smrg } 853848b8605Smrg} 854848b8605Smrg 855848b8605Smrg 856848b8605SmrgGLboolean 857848b8605Smrg_mesa_texstore_can_use_memcpy(struct gl_context *ctx, 858848b8605Smrg GLenum baseInternalFormat, mesa_format dstFormat, 859848b8605Smrg GLenum srcFormat, GLenum srcType, 860848b8605Smrg const struct gl_pixelstore_attrib *srcPacking) 861848b8605Smrg{ 862848b8605Smrg if (_mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) { 863848b8605Smrg return GL_FALSE; 864848b8605Smrg } 865848b8605Smrg 866848b8605Smrg /* The base internal format and the base Mesa format must match. */ 867848b8605Smrg if (baseInternalFormat != _mesa_get_format_base_format(dstFormat)) { 868848b8605Smrg return GL_FALSE; 869848b8605Smrg } 870848b8605Smrg 871848b8605Smrg /* The Mesa format must match the input format and type. */ 872848b8605Smrg if (!_mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, 873b8e80941Smrg srcPacking->SwapBytes, NULL)) { 874848b8605Smrg return GL_FALSE; 875848b8605Smrg } 876848b8605Smrg 877848b8605Smrg /* Depth texture data needs clamping in following cases: 878848b8605Smrg * - Floating point dstFormat with signed srcType: clamp to [0.0, 1.0]. 879848b8605Smrg * - Fixed point dstFormat with signed srcType: clamp to [0, 2^n -1]. 880848b8605Smrg * 881848b8605Smrg * All the cases except one (float dstFormat with float srcType) are ruled 882848b8605Smrg * out by _mesa_format_matches_format_and_type() check above. Handle the 883848b8605Smrg * remaining case here. 884848b8605Smrg */ 885848b8605Smrg if ((baseInternalFormat == GL_DEPTH_COMPONENT || 886848b8605Smrg baseInternalFormat == GL_DEPTH_STENCIL) && 887848b8605Smrg (srcType == GL_FLOAT || 888848b8605Smrg srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)) { 889848b8605Smrg return GL_FALSE; 890848b8605Smrg } 891848b8605Smrg 892848b8605Smrg return GL_TRUE; 893848b8605Smrg} 894848b8605Smrg 895848b8605Smrgstatic GLboolean 896848b8605Smrg_mesa_texstore_memcpy(TEXSTORE_PARAMS) 897848b8605Smrg{ 898848b8605Smrg if (!_mesa_texstore_can_use_memcpy(ctx, baseInternalFormat, dstFormat, 899848b8605Smrg srcFormat, srcType, srcPacking)) { 900848b8605Smrg return GL_FALSE; 901848b8605Smrg } 902848b8605Smrg 903b8e80941Smrg _mesa_memcpy_texture(ctx, dims, 904b8e80941Smrg dstFormat, 905b8e80941Smrg dstRowStride, dstSlices, 906b8e80941Smrg srcWidth, srcHeight, srcDepth, srcFormat, srcType, 907b8e80941Smrg srcAddr, srcPacking); 908848b8605Smrg return GL_TRUE; 909848b8605Smrg} 910b8e80941Smrg 911b8e80941Smrg 912848b8605Smrg/** 913848b8605Smrg * Store user data into texture memory. 914848b8605Smrg * Called via glTex[Sub]Image1/2/3D() 915848b8605Smrg * \return GL_TRUE for success, GL_FALSE for failure (out of memory). 916848b8605Smrg */ 917848b8605SmrgGLboolean 918848b8605Smrg_mesa_texstore(TEXSTORE_PARAMS) 919848b8605Smrg{ 920848b8605Smrg if (_mesa_texstore_memcpy(ctx, dims, baseInternalFormat, 921848b8605Smrg dstFormat, 922848b8605Smrg dstRowStride, dstSlices, 923848b8605Smrg srcWidth, srcHeight, srcDepth, 924848b8605Smrg srcFormat, srcType, srcAddr, srcPacking)) { 925848b8605Smrg return GL_TRUE; 926848b8605Smrg } 927848b8605Smrg 928848b8605Smrg if (_mesa_is_depth_or_stencil_format(baseInternalFormat)) { 929848b8605Smrg return texstore_depth_stencil(ctx, dims, baseInternalFormat, 930848b8605Smrg dstFormat, dstRowStride, dstSlices, 931848b8605Smrg srcWidth, srcHeight, srcDepth, 932848b8605Smrg srcFormat, srcType, srcAddr, srcPacking); 933848b8605Smrg } else if (_mesa_is_format_compressed(dstFormat)) { 934848b8605Smrg return texstore_compressed(ctx, dims, baseInternalFormat, 935848b8605Smrg dstFormat, dstRowStride, dstSlices, 936848b8605Smrg srcWidth, srcHeight, srcDepth, 937848b8605Smrg srcFormat, srcType, srcAddr, srcPacking); 938848b8605Smrg } else { 939848b8605Smrg return texstore_rgba(ctx, dims, baseInternalFormat, 940848b8605Smrg dstFormat, dstRowStride, dstSlices, 941848b8605Smrg srcWidth, srcHeight, srcDepth, 942848b8605Smrg srcFormat, srcType, srcAddr, srcPacking); 943848b8605Smrg } 944848b8605Smrg} 945848b8605Smrg 946848b8605Smrg 947848b8605Smrg/** 948848b8605Smrg * Normally, we'll only _write_ texel data to a texture when we map it. 949848b8605Smrg * But if the user is providing depth or stencil values and the texture 950848b8605Smrg * image is a combined depth/stencil format, we'll actually read from 951848b8605Smrg * the texture buffer too (in order to insert the depth or stencil values. 952848b8605Smrg * \param userFormat the user-provided image format 953848b8605Smrg * \param texFormat the destination texture format 954848b8605Smrg */ 955848b8605Smrgstatic GLbitfield 956848b8605Smrgget_read_write_mode(GLenum userFormat, mesa_format texFormat) 957848b8605Smrg{ 958848b8605Smrg if ((userFormat == GL_STENCIL_INDEX || userFormat == GL_DEPTH_COMPONENT) 959848b8605Smrg && _mesa_get_format_base_format(texFormat) == GL_DEPTH_STENCIL) 960848b8605Smrg return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; 961848b8605Smrg else 962848b8605Smrg return GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT; 963848b8605Smrg} 964848b8605Smrg 965848b8605Smrg 966848b8605Smrg/** 967848b8605Smrg * Helper function for storing 1D, 2D, 3D whole and subimages into texture 968848b8605Smrg * memory. 969848b8605Smrg * The source of the image data may be user memory or a PBO. In the later 970848b8605Smrg * case, we'll map the PBO, copy from it, then unmap it. 971848b8605Smrg */ 972848b8605Smrgstatic void 973848b8605Smrgstore_texsubimage(struct gl_context *ctx, 974848b8605Smrg struct gl_texture_image *texImage, 975848b8605Smrg GLint xoffset, GLint yoffset, GLint zoffset, 976848b8605Smrg GLint width, GLint height, GLint depth, 977848b8605Smrg GLenum format, GLenum type, const GLvoid *pixels, 978848b8605Smrg const struct gl_pixelstore_attrib *packing, 979848b8605Smrg const char *caller) 980848b8605Smrg 981848b8605Smrg{ 982848b8605Smrg const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat); 983848b8605Smrg const GLenum target = texImage->TexObject->Target; 984848b8605Smrg GLboolean success = GL_FALSE; 985848b8605Smrg GLuint dims, slice, numSlices = 1, sliceOffset = 0; 986848b8605Smrg GLint srcImageStride = 0; 987848b8605Smrg const GLubyte *src; 988848b8605Smrg 989848b8605Smrg assert(xoffset + width <= texImage->Width); 990848b8605Smrg assert(yoffset + height <= texImage->Height); 991848b8605Smrg assert(zoffset + depth <= texImage->Depth); 992848b8605Smrg 993848b8605Smrg switch (target) { 994848b8605Smrg case GL_TEXTURE_1D: 995848b8605Smrg dims = 1; 996848b8605Smrg break; 997848b8605Smrg case GL_TEXTURE_2D_ARRAY: 998848b8605Smrg case GL_TEXTURE_CUBE_MAP_ARRAY: 999848b8605Smrg case GL_TEXTURE_3D: 1000848b8605Smrg dims = 3; 1001848b8605Smrg break; 1002848b8605Smrg default: 1003848b8605Smrg dims = 2; 1004848b8605Smrg } 1005848b8605Smrg 1006848b8605Smrg /* get pointer to src pixels (may be in a pbo which we'll map here) */ 1007848b8605Smrg src = (const GLubyte *) 1008848b8605Smrg _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, 1009848b8605Smrg format, type, pixels, packing, caller); 1010848b8605Smrg if (!src) 1011848b8605Smrg return; 1012848b8605Smrg 1013848b8605Smrg /* compute slice info (and do some sanity checks) */ 1014848b8605Smrg switch (target) { 1015848b8605Smrg case GL_TEXTURE_2D: 1016b8e80941Smrg case GL_TEXTURE_2D_MULTISAMPLE: 1017848b8605Smrg case GL_TEXTURE_RECTANGLE: 1018848b8605Smrg case GL_TEXTURE_CUBE_MAP: 1019848b8605Smrg case GL_TEXTURE_EXTERNAL_OES: 1020848b8605Smrg /* one image slice, nothing special needs to be done */ 1021848b8605Smrg break; 1022848b8605Smrg case GL_TEXTURE_1D: 1023848b8605Smrg assert(height == 1); 1024848b8605Smrg assert(depth == 1); 1025848b8605Smrg assert(yoffset == 0); 1026848b8605Smrg assert(zoffset == 0); 1027848b8605Smrg break; 1028848b8605Smrg case GL_TEXTURE_1D_ARRAY: 1029848b8605Smrg assert(depth == 1); 1030848b8605Smrg assert(zoffset == 0); 1031848b8605Smrg numSlices = height; 1032848b8605Smrg sliceOffset = yoffset; 1033848b8605Smrg height = 1; 1034848b8605Smrg yoffset = 0; 1035848b8605Smrg srcImageStride = _mesa_image_row_stride(packing, width, format, type); 1036848b8605Smrg break; 1037848b8605Smrg case GL_TEXTURE_2D_ARRAY: 1038b8e80941Smrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1039848b8605Smrg numSlices = depth; 1040848b8605Smrg sliceOffset = zoffset; 1041848b8605Smrg depth = 1; 1042848b8605Smrg zoffset = 0; 1043848b8605Smrg srcImageStride = _mesa_image_image_stride(packing, width, height, 1044848b8605Smrg format, type); 1045848b8605Smrg break; 1046848b8605Smrg case GL_TEXTURE_3D: 1047848b8605Smrg /* we'll store 3D images as a series of slices */ 1048848b8605Smrg numSlices = depth; 1049848b8605Smrg sliceOffset = zoffset; 1050848b8605Smrg srcImageStride = _mesa_image_image_stride(packing, width, height, 1051848b8605Smrg format, type); 1052848b8605Smrg break; 1053848b8605Smrg case GL_TEXTURE_CUBE_MAP_ARRAY: 1054848b8605Smrg numSlices = depth; 1055848b8605Smrg sliceOffset = zoffset; 1056848b8605Smrg srcImageStride = _mesa_image_image_stride(packing, width, height, 1057848b8605Smrg format, type); 1058848b8605Smrg break; 1059848b8605Smrg default: 1060b8e80941Smrg _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()", 1061b8e80941Smrg target); 1062848b8605Smrg return; 1063848b8605Smrg } 1064848b8605Smrg 1065848b8605Smrg assert(numSlices == 1 || srcImageStride != 0); 1066848b8605Smrg 1067848b8605Smrg for (slice = 0; slice < numSlices; slice++) { 1068848b8605Smrg GLubyte *dstMap; 1069848b8605Smrg GLint dstRowStride; 1070848b8605Smrg 1071848b8605Smrg ctx->Driver.MapTextureImage(ctx, texImage, 1072848b8605Smrg slice + sliceOffset, 1073848b8605Smrg xoffset, yoffset, width, height, 1074848b8605Smrg mapMode, &dstMap, &dstRowStride); 1075848b8605Smrg if (dstMap) { 1076848b8605Smrg /* Note: we're only storing a 2D (or 1D) slice at a time but we need 1077848b8605Smrg * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is 1078848b8605Smrg * used for 3D images. 1079848b8605Smrg */ 1080848b8605Smrg success = _mesa_texstore(ctx, dims, texImage->_BaseFormat, 1081848b8605Smrg texImage->TexFormat, 1082848b8605Smrg dstRowStride, 1083848b8605Smrg &dstMap, 1084848b8605Smrg width, height, 1, /* w, h, d */ 1085848b8605Smrg format, type, src, packing); 1086848b8605Smrg 1087848b8605Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset); 1088848b8605Smrg } 1089848b8605Smrg 1090848b8605Smrg src += srcImageStride; 1091848b8605Smrg 1092848b8605Smrg if (!success) 1093848b8605Smrg break; 1094848b8605Smrg } 1095848b8605Smrg 1096848b8605Smrg if (!success) 1097848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 1098848b8605Smrg 1099848b8605Smrg _mesa_unmap_teximage_pbo(ctx, packing); 1100848b8605Smrg} 1101848b8605Smrg 1102848b8605Smrg 1103848b8605Smrg 1104848b8605Smrg/** 1105848b8605Smrg * Fallback code for ctx->Driver.TexImage(). 1106848b8605Smrg * Basically, allocate storage for the texture image, then copy the 1107848b8605Smrg * user's image into it. 1108848b8605Smrg */ 1109848b8605Smrgvoid 1110848b8605Smrg_mesa_store_teximage(struct gl_context *ctx, 1111848b8605Smrg GLuint dims, 1112848b8605Smrg struct gl_texture_image *texImage, 1113848b8605Smrg GLenum format, GLenum type, const GLvoid *pixels, 1114848b8605Smrg const struct gl_pixelstore_attrib *packing) 1115848b8605Smrg{ 1116848b8605Smrg assert(dims == 1 || dims == 2 || dims == 3); 1117848b8605Smrg 1118848b8605Smrg if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0) 1119848b8605Smrg return; 1120848b8605Smrg 1121848b8605Smrg /* allocate storage for texture data */ 1122848b8605Smrg if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) { 1123848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); 1124848b8605Smrg return; 1125848b8605Smrg } 1126848b8605Smrg 1127848b8605Smrg store_texsubimage(ctx, texImage, 1128848b8605Smrg 0, 0, 0, texImage->Width, texImage->Height, texImage->Depth, 1129848b8605Smrg format, type, pixels, packing, "glTexImage"); 1130848b8605Smrg} 1131848b8605Smrg 1132848b8605Smrg 1133848b8605Smrg/* 1134848b8605Smrg * Fallback for Driver.TexSubImage(). 1135848b8605Smrg */ 1136848b8605Smrgvoid 1137848b8605Smrg_mesa_store_texsubimage(struct gl_context *ctx, GLuint dims, 1138848b8605Smrg struct gl_texture_image *texImage, 1139848b8605Smrg GLint xoffset, GLint yoffset, GLint zoffset, 1140848b8605Smrg GLint width, GLint height, GLint depth, 1141848b8605Smrg GLenum format, GLenum type, const void *pixels, 1142848b8605Smrg const struct gl_pixelstore_attrib *packing) 1143848b8605Smrg{ 1144848b8605Smrg store_texsubimage(ctx, texImage, 1145848b8605Smrg xoffset, yoffset, zoffset, width, height, depth, 1146848b8605Smrg format, type, pixels, packing, "glTexSubImage"); 1147848b8605Smrg} 1148848b8605Smrg 1149848b8605Smrgstatic void 1150848b8605Smrgclear_image_to_zero(GLubyte *dstMap, GLint dstRowStride, 1151848b8605Smrg GLsizei width, GLsizei height, 1152848b8605Smrg GLsizei clearValueSize) 1153848b8605Smrg{ 1154848b8605Smrg GLsizei y; 1155848b8605Smrg 1156848b8605Smrg for (y = 0; y < height; y++) { 1157848b8605Smrg memset(dstMap, 0, clearValueSize * width); 1158848b8605Smrg dstMap += dstRowStride; 1159848b8605Smrg } 1160848b8605Smrg} 1161848b8605Smrg 1162848b8605Smrgstatic void 1163848b8605Smrgclear_image_to_value(GLubyte *dstMap, GLint dstRowStride, 1164848b8605Smrg GLsizei width, GLsizei height, 1165848b8605Smrg const GLvoid *clearValue, 1166848b8605Smrg GLsizei clearValueSize) 1167848b8605Smrg{ 1168848b8605Smrg GLsizei y, x; 1169848b8605Smrg 1170848b8605Smrg for (y = 0; y < height; y++) { 1171848b8605Smrg for (x = 0; x < width; x++) { 1172848b8605Smrg memcpy(dstMap, clearValue, clearValueSize); 1173848b8605Smrg dstMap += clearValueSize; 1174848b8605Smrg } 1175848b8605Smrg dstMap += dstRowStride - clearValueSize * width; 1176848b8605Smrg } 1177848b8605Smrg} 1178848b8605Smrg 1179848b8605Smrg/* 1180848b8605Smrg * Fallback for Driver.ClearTexSubImage(). 1181848b8605Smrg */ 1182848b8605Smrgvoid 1183848b8605Smrg_mesa_store_cleartexsubimage(struct gl_context *ctx, 1184848b8605Smrg struct gl_texture_image *texImage, 1185848b8605Smrg GLint xoffset, GLint yoffset, GLint zoffset, 1186848b8605Smrg GLsizei width, GLsizei height, GLsizei depth, 1187848b8605Smrg const GLvoid *clearValue) 1188848b8605Smrg{ 1189848b8605Smrg GLubyte *dstMap; 1190848b8605Smrg GLint dstRowStride; 1191848b8605Smrg GLsizeiptr clearValueSize; 1192848b8605Smrg GLsizei z; 1193848b8605Smrg 1194848b8605Smrg clearValueSize = _mesa_get_format_bytes(texImage->TexFormat); 1195848b8605Smrg 1196848b8605Smrg for (z = 0; z < depth; z++) { 1197848b8605Smrg ctx->Driver.MapTextureImage(ctx, texImage, 1198848b8605Smrg z + zoffset, xoffset, yoffset, 1199848b8605Smrg width, height, 1200848b8605Smrg GL_MAP_WRITE_BIT, 1201848b8605Smrg &dstMap, &dstRowStride); 1202848b8605Smrg if (dstMap == NULL) { 1203848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearTex*Image"); 1204848b8605Smrg return; 1205848b8605Smrg } 1206848b8605Smrg 1207848b8605Smrg if (clearValue) { 1208848b8605Smrg clear_image_to_value(dstMap, dstRowStride, 1209848b8605Smrg width, height, 1210848b8605Smrg clearValue, 1211848b8605Smrg clearValueSize); 1212848b8605Smrg } else { 1213848b8605Smrg clear_image_to_zero(dstMap, dstRowStride, 1214848b8605Smrg width, height, 1215848b8605Smrg clearValueSize); 1216848b8605Smrg } 1217848b8605Smrg 1218848b8605Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, z + zoffset); 1219848b8605Smrg } 1220848b8605Smrg} 1221848b8605Smrg 1222848b8605Smrg/** 1223848b8605Smrg * Fallback for Driver.CompressedTexImage() 1224848b8605Smrg */ 1225848b8605Smrgvoid 1226848b8605Smrg_mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, 1227848b8605Smrg struct gl_texture_image *texImage, 1228848b8605Smrg GLsizei imageSize, const GLvoid *data) 1229848b8605Smrg{ 1230848b8605Smrg /* only 2D and 3D compressed images are supported at this time */ 1231848b8605Smrg if (dims == 1) { 1232848b8605Smrg _mesa_problem(ctx, "Unexpected glCompressedTexImage1D call"); 1233848b8605Smrg return; 1234848b8605Smrg } 1235848b8605Smrg 1236848b8605Smrg /* This is pretty simple, because unlike the general texstore path we don't 1237848b8605Smrg * have to worry about the usual image unpacking or image transfer 1238848b8605Smrg * operations. 1239848b8605Smrg */ 1240b8e80941Smrg assert(texImage); 1241b8e80941Smrg assert(texImage->Width > 0); 1242b8e80941Smrg assert(texImage->Height > 0); 1243b8e80941Smrg assert(texImage->Depth > 0); 1244848b8605Smrg 1245848b8605Smrg /* allocate storage for texture data */ 1246848b8605Smrg if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) { 1247848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage%uD", dims); 1248848b8605Smrg return; 1249848b8605Smrg } 1250848b8605Smrg 1251b8e80941Smrg ctx->Driver.CompressedTexSubImage(ctx, dims, texImage, 1252b8e80941Smrg 0, 0, 0, 1253b8e80941Smrg texImage->Width, texImage->Height, texImage->Depth, 1254b8e80941Smrg texImage->TexFormat, 1255b8e80941Smrg imageSize, data); 1256848b8605Smrg} 1257848b8605Smrg 1258848b8605Smrg 1259848b8605Smrg/** 1260848b8605Smrg * Compute compressed_pixelstore parameters for copying compressed 1261848b8605Smrg * texture data. 1262848b8605Smrg * \param dims number of texture image dimensions: 1, 2 or 3 1263848b8605Smrg * \param texFormat the compressed texture format 1264848b8605Smrg * \param width, height, depth size of image to copy 1265848b8605Smrg * \param packing pixelstore parameters describing user-space image packing 1266848b8605Smrg * \param store returns the compressed_pixelstore parameters 1267848b8605Smrg */ 1268848b8605Smrgvoid 1269848b8605Smrg_mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat, 1270848b8605Smrg GLsizei width, GLsizei height, 1271848b8605Smrg GLsizei depth, 1272848b8605Smrg const struct gl_pixelstore_attrib *packing, 1273848b8605Smrg struct compressed_pixelstore *store) 1274848b8605Smrg{ 1275b8e80941Smrg GLuint bw, bh, bd; 1276848b8605Smrg 1277b8e80941Smrg _mesa_get_format_block_size_3d(texFormat, &bw, &bh, &bd); 1278848b8605Smrg 1279848b8605Smrg store->SkipBytes = 0; 1280848b8605Smrg store->TotalBytesPerRow = store->CopyBytesPerRow = 1281848b8605Smrg _mesa_format_row_stride(texFormat, width); 1282848b8605Smrg store->TotalRowsPerSlice = store->CopyRowsPerSlice = 1283848b8605Smrg (height + bh - 1) / bh; 1284b8e80941Smrg store->CopySlices = (depth + bd - 1) / bd; 1285848b8605Smrg 1286848b8605Smrg if (packing->CompressedBlockWidth && 1287848b8605Smrg packing->CompressedBlockSize) { 1288848b8605Smrg 1289848b8605Smrg bw = packing->CompressedBlockWidth; 1290848b8605Smrg 1291848b8605Smrg if (packing->RowLength) { 1292848b8605Smrg store->TotalBytesPerRow = packing->CompressedBlockSize * 1293848b8605Smrg ((packing->RowLength + bw - 1) / bw); 1294848b8605Smrg } 1295848b8605Smrg 1296b8e80941Smrg store->SkipBytes += 1297b8e80941Smrg packing->SkipPixels * packing->CompressedBlockSize / bw; 1298848b8605Smrg } 1299848b8605Smrg 1300848b8605Smrg if (dims > 1 && packing->CompressedBlockHeight && 1301848b8605Smrg packing->CompressedBlockSize) { 1302848b8605Smrg 1303848b8605Smrg bh = packing->CompressedBlockHeight; 1304848b8605Smrg 1305848b8605Smrg store->SkipBytes += packing->SkipRows * store->TotalBytesPerRow / bh; 1306848b8605Smrg store->CopyRowsPerSlice = (height + bh - 1) / bh; /* rows in blocks */ 1307848b8605Smrg 1308848b8605Smrg if (packing->ImageHeight) { 1309848b8605Smrg store->TotalRowsPerSlice = (packing->ImageHeight + bh - 1) / bh; 1310848b8605Smrg } 1311848b8605Smrg } 1312848b8605Smrg 1313848b8605Smrg if (dims > 2 && packing->CompressedBlockDepth && 1314848b8605Smrg packing->CompressedBlockSize) { 1315848b8605Smrg 1316848b8605Smrg int bd = packing->CompressedBlockDepth; 1317848b8605Smrg 1318848b8605Smrg store->SkipBytes += packing->SkipImages * store->TotalBytesPerRow * 1319848b8605Smrg store->TotalRowsPerSlice / bd; 1320848b8605Smrg } 1321848b8605Smrg} 1322848b8605Smrg 1323848b8605Smrg 1324848b8605Smrg/** 1325848b8605Smrg * Fallback for Driver.CompressedTexSubImage() 1326848b8605Smrg */ 1327848b8605Smrgvoid 1328848b8605Smrg_mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, 1329848b8605Smrg struct gl_texture_image *texImage, 1330848b8605Smrg GLint xoffset, GLint yoffset, GLint zoffset, 1331848b8605Smrg GLsizei width, GLsizei height, GLsizei depth, 1332848b8605Smrg GLenum format, 1333848b8605Smrg GLsizei imageSize, const GLvoid *data) 1334848b8605Smrg{ 1335848b8605Smrg struct compressed_pixelstore store; 1336848b8605Smrg GLint dstRowStride; 1337848b8605Smrg GLint i, slice; 1338848b8605Smrg GLubyte *dstMap; 1339848b8605Smrg const GLubyte *src; 1340848b8605Smrg 1341848b8605Smrg if (dims == 1) { 1342848b8605Smrg _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call"); 1343848b8605Smrg return; 1344848b8605Smrg } 1345848b8605Smrg 1346848b8605Smrg _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat, 1347848b8605Smrg width, height, depth, 1348848b8605Smrg &ctx->Unpack, &store); 1349848b8605Smrg 1350848b8605Smrg /* get pointer to src pixels (may be in a pbo which we'll map here) */ 1351848b8605Smrg data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data, 1352848b8605Smrg &ctx->Unpack, 1353848b8605Smrg "glCompressedTexSubImage"); 1354848b8605Smrg if (!data) 1355848b8605Smrg return; 1356848b8605Smrg 1357848b8605Smrg src = (const GLubyte *) data + store.SkipBytes; 1358848b8605Smrg 1359848b8605Smrg for (slice = 0; slice < store.CopySlices; slice++) { 1360848b8605Smrg /* Map dest texture buffer */ 1361848b8605Smrg ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset, 1362848b8605Smrg xoffset, yoffset, width, height, 1363848b8605Smrg GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, 1364848b8605Smrg &dstMap, &dstRowStride); 1365848b8605Smrg 1366848b8605Smrg if (dstMap) { 1367848b8605Smrg 1368848b8605Smrg /* copy rows of blocks */ 1369b8e80941Smrg if (dstRowStride == store.TotalBytesPerRow && 1370b8e80941Smrg dstRowStride == store.CopyBytesPerRow) { 1371b8e80941Smrg memcpy(dstMap, src, store.CopyBytesPerRow * store.CopyRowsPerSlice); 1372b8e80941Smrg src += store.CopyBytesPerRow * store.CopyRowsPerSlice; 1373b8e80941Smrg } 1374b8e80941Smrg else { 1375b8e80941Smrg for (i = 0; i < store.CopyRowsPerSlice; i++) { 1376b8e80941Smrg memcpy(dstMap, src, store.CopyBytesPerRow); 1377b8e80941Smrg dstMap += dstRowStride; 1378b8e80941Smrg src += store.TotalBytesPerRow; 1379b8e80941Smrg } 1380848b8605Smrg } 1381848b8605Smrg 1382848b8605Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset); 1383848b8605Smrg 1384848b8605Smrg /* advance to next slice */ 1385b8e80941Smrg src += store.TotalBytesPerRow * (store.TotalRowsPerSlice 1386b8e80941Smrg - store.CopyRowsPerSlice); 1387848b8605Smrg } 1388848b8605Smrg else { 1389848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage%uD", 1390848b8605Smrg dims); 1391848b8605Smrg } 1392848b8605Smrg } 1393848b8605Smrg 1394848b8605Smrg _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); 1395848b8605Smrg} 1396