/** * Initialization of the context's Color attribute group. * * \param ctx GL context. * * Initializes the related fields in the context color attribute group, * __struct gl_contextRec::Color. */ void _mesa_init_color( struct gl_context * ctx ) { GLuint i; /* Color buffer group */ ctx->Color.IndexMask = ~0u; memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask)); ctx->Color.ClearIndex = 0; ASSIGN_4V( ctx->Color.ClearColor.f, 0, 0, 0, 0 ); ctx->Color.AlphaEnabled = GL_FALSE; ctx->Color.AlphaFunc = GL_ALWAYS; ctx->Color.AlphaRef = 0; ctx->Color.BlendEnabled = 0x0; for (i = 0; i < ARRAY_SIZE(ctx->Color.Blend); i++) { ctx->Color.Blend[i].SrcRGB = GL_ONE; ctx->Color.Blend[i].DstRGB = GL_ZERO; ctx->Color.Blend[i].SrcA = GL_ONE; ctx->Color.Blend[i].DstA = GL_ZERO; ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD; ctx->Color.Blend[i].EquationA = GL_FUNC_ADD; } ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 ); ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 ); ctx->Color.IndexLogicOpEnabled = GL_FALSE; ctx->Color.ColorLogicOpEnabled = GL_FALSE; ctx->Color.LogicOp = GL_COPY; ctx->Color.DitherFlag = GL_TRUE; /* GL_FRONT is not possible on GLES. Instead GL_BACK will render to either * the front or the back buffer depending on the config */ if (ctx->Visual.doubleBufferMode || _mesa_is_gles(ctx)) { ctx->Color.DrawBuffer[0] = GL_BACK; } else { ctx->Color.DrawBuffer[0] = GL_FRONT; } ctx->Color.ClampFragmentColor = ctx->API == API_OPENGL_COMPAT ? GL_FIXED_ONLY_ARB : GL_FALSE; ctx->Color._ClampFragmentColor = GL_FALSE; ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB; /* GLES 1/2/3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled * if EGL_KHR_gl_colorspace has been used to request sRGB. */ ctx->Color.sRGBEnabled = _mesa_is_gles(ctx); ctx->Color.BlendCoherent = true; }
void GLAPIENTRY _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) { GET_CURRENT_CONTEXT(ctx); struct gl_image_unit *u; if (!validate_bind_image_texture(ctx, unit, texture, level, layered, layer, access, format)) return; u = &ctx->ImageUnits[unit]; FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; if (texture) { struct gl_texture_object *t = _mesa_lookup_texture(ctx, texture); if (!t) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)"); return; } /* From section 8.22 "Texture Image Loads and Stores" of the OpenGL ES * 3.1 spec: * * "An INVALID_OPERATION error is generated if texture is not the name * of an immutable texture object." */ if (_mesa_is_gles(ctx) && !t->Immutable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTexture(!immutable)"); return; } _mesa_reference_texobj(&u->TexObj, t); } else { _mesa_reference_texobj(&u->TexObj, NULL); } u->Level = level; u->Access = access; u->Format = format; u->_ActualFormat = _mesa_get_shader_image_format(format); if (u->TexObj && _mesa_tex_target_is_layered(u->TexObj->Target)) { u->Layered = layered; u->Layer = layer; u->_Layer = (u->Layered ? 0 : u->Layer); } else { u->Layered = GL_FALSE; u->Layer = 0; } if (ctx->Driver.BindImageTexture) ctx->Driver.BindImageTexture(ctx, u, u->TexObj, level, layered, layer, access, format); }
/** * Attach shader to a shader program. */ static void attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg; struct gl_shader *sh; GLuint i, n; const bool same_type_disallowed = _mesa_is_gles(ctx); shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader"); if (!shProg) return; sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader"); if (!sh) { return; } n = shProg->NumShaders; for (i = 0; i < n; i++) { if (shProg->Shaders[i] == sh) { /* The shader is already attched to this program. The * GL_ARB_shader_objects spec says: * * "The error INVALID_OPERATION is generated by AttachObjectARB * if <obj> is already attached to <containerObj>." */ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); return; } else if (same_type_disallowed && shProg->Shaders[i]->Type == sh->Type) { /* Shader with the same type is already attached to this program, * OpenGL ES 2.0 and 3.0 specs say: * * "Multiple shader objects of the same type may not be attached * to a single program object. [...] The error INVALID_OPERATION * is generated if [...] another shader object of the same type * as shader is already attached to program." */ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); return; } } /* grow list */ shProg->Shaders = (struct gl_shader **) _mesa_realloc(shProg->Shaders, n * sizeof(struct gl_shader *), (n + 1) * sizeof(struct gl_shader *)); if (!shProg->Shaders) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader"); return; } /* append */ shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */ _mesa_reference_shader(ctx, &shProg->Shaders[n], sh); shProg->NumShaders++; }
static size_t brw_query_samples_for_format(struct gl_context *ctx, GLenum target, GLenum internalFormat, int samples[16]) { struct brw_context *brw = brw_context(ctx); const struct gen_device_info *devinfo = &brw->screen->devinfo; (void) target; (void) internalFormat; switch (devinfo->gen) { case 11: case 10: case 9: samples[0] = 16; samples[1] = 8; samples[2] = 4; samples[3] = 2; return 4; case 8: samples[0] = 8; samples[1] = 4; samples[2] = 2; return 3; case 7: if (internalFormat == GL_RGBA32F && _mesa_is_gles(ctx)) { /* For GLES, we are allowed to return a smaller number of samples for * GL_RGBA32F. See OpenGLES 3.2 spec, section 20.3.1 Internal Format * Query Parameters, under SAMPLES: * * "A value less than or equal to the value of MAX_SAMPLES, if * internalformat is RGBA16F, R32F, RG32F, or RGBA32F." * * In brw_render_target_supported, we prevent formats with a size * greater than 8 bytes from using 8x MSAA on gen7. */ samples[0] = 4; return 1; } else { samples[0] = 8; samples[1] = 4; return 2; } case 6: samples[0] = 4; return 1; default: assert(devinfo->gen < 6); samples[0] = 1; return 1; } }
/** * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D * into the corresponding Mesa texture target index. * Note that proxy targets are not valid here. * \return TEXTURE_x_INDEX or -1 if target is invalid */ static GLint target_enum_to_index(struct gl_context *ctx, GLenum target) { switch (target) { case GL_TEXTURE_1D: return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1; case GL_TEXTURE_2D: return TEXTURE_2D_INDEX; case GL_TEXTURE_3D: return TEXTURE_3D_INDEX; case GL_TEXTURE_CUBE_MAP_ARB: return ctx->Extensions.ARB_texture_cube_map ? TEXTURE_CUBE_INDEX : -1; case GL_TEXTURE_RECTANGLE_NV: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle ? TEXTURE_RECT_INDEX : -1; case GL_TEXTURE_1D_ARRAY_EXT: return _mesa_is_desktop_gl(ctx) && (ctx->Extensions.EXT_texture_array || ctx->Extensions.MESA_texture_array) ? TEXTURE_1D_ARRAY_INDEX : -1; case GL_TEXTURE_2D_ARRAY_EXT: return (_mesa_is_desktop_gl(ctx) && (ctx->Extensions.EXT_texture_array || ctx->Extensions.MESA_texture_array)) || _mesa_is_gles3(ctx) ? TEXTURE_2D_ARRAY_INDEX : -1; case GL_TEXTURE_BUFFER_ARB: return ctx->API == API_OPENGL_CORE && ctx->Extensions.ARB_texture_buffer_object ? TEXTURE_BUFFER_INDEX : -1; case GL_TEXTURE_EXTERNAL_OES: return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external ? TEXTURE_EXTERNAL_INDEX : -1; case GL_TEXTURE_CUBE_MAP_ARRAY: return TEXTURE_CUBE_ARRAY_INDEX; case GL_TEXTURE_2D_MULTISAMPLE: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample ? TEXTURE_2D_MULTISAMPLE_INDEX: -1; case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: -1; default: return -1; } }
/** * Generate all the mipmap levels below the base level. * Note: this GL function would be more useful if one could specify a * cube face, a set of array slices, etc. */ void GLAPIENTRY _mesa_GenerateMipmap(GLenum target) { struct gl_texture_image *srcImage; struct gl_texture_object *texObj; GLboolean error; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); switch (target) { case GL_TEXTURE_1D: error = _mesa_is_gles(ctx); break; case GL_TEXTURE_2D: error = GL_FALSE; break; case GL_TEXTURE_3D: error = ctx->API == API_OPENGLES; break; case GL_TEXTURE_CUBE_MAP: error = !ctx->Extensions.ARB_texture_cube_map; break; case GL_TEXTURE_1D_ARRAY: error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array; break; case GL_TEXTURE_2D_ARRAY: error = (_mesa_is_gles(ctx) && ctx->Version < 30) || !ctx->Extensions.EXT_texture_array; break; case GL_TEXTURE_CUBE_MAP_ARRAY: error = _mesa_is_gles(ctx) || !ctx->Extensions.ARB_texture_cube_map_array; break; default: error = GL_TRUE; } if (error) { _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)", _mesa_lookup_enum_by_nr(target)); return; } texObj = _mesa_get_current_tex_object(ctx, target); if (texObj->BaseLevel >= texObj->MaxLevel) { /* nothing to do */ return; } if (texObj->Target == GL_TEXTURE_CUBE_MAP && !_mesa_cube_complete(texObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGenerateMipmap(incomplete cube map)"); return; } _mesa_lock_texture(ctx, texObj); srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); if (!srcImage) { _mesa_unlock_texture(ctx, texObj); _mesa_error(ctx, GL_INVALID_OPERATION, "glGenerateMipmap(zero size base image)"); return; } if (_mesa_is_enum_format_integer(srcImage->InternalFormat) || _mesa_is_depthstencil_format(srcImage->InternalFormat) || _mesa_is_stencil_format(srcImage->InternalFormat)) { _mesa_unlock_texture(ctx, texObj); _mesa_error(ctx, GL_INVALID_OPERATION, "glGenerateMipmap(invalid internal format)"); return; } if (target == GL_TEXTURE_CUBE_MAP) { GLuint face; for (face = 0; face < 6; face++) ctx->Driver.GenerateMipmap(ctx, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, texObj); } else { ctx->Driver.GenerateMipmap(ctx, target, texObj); } _mesa_unlock_texture(ctx, texObj); }
/** * Helper routine used by glDrawBuffer and glDrawBuffersARB. * Given a GLenum naming one or more color buffers (such as * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. */ static GLbitfield draw_buffer_enum_to_bitmask(const struct gl_context *ctx, GLenum buffer) { switch (buffer) { case GL_NONE: return 0; case GL_FRONT: return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; case GL_BACK: if (_mesa_is_gles(ctx)) { /* Page 181 (page 192 of the PDF) in section 4.2.1 of the OpenGL * ES 3.0.1 specification says: * * "When draw buffer zero is BACK, color values are written * into the sole buffer for single-buffered contexts, or into * the back buffer for double-buffered contexts." * * Since there is no stereo rendering in ES 3.0, only return the * LEFT bits. This also satisfies the "n must be 1" requirement. * * We also do this for GLES 1 and 2 because those APIs have no * concept of selecting the front and back buffer anyway and it's * convenient to be able to maintain the magic behaviour of * GL_BACK in that case. */ if (ctx->DrawBuffer->Visual.doubleBufferMode) return BUFFER_BIT_BACK_LEFT; return BUFFER_BIT_FRONT_LEFT; } return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; case GL_RIGHT: return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; case GL_FRONT_RIGHT: return BUFFER_BIT_FRONT_RIGHT; case GL_BACK_RIGHT: return BUFFER_BIT_BACK_RIGHT; case GL_BACK_LEFT: return BUFFER_BIT_BACK_LEFT; case GL_FRONT_AND_BACK: return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; case GL_LEFT: return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; case GL_FRONT_LEFT: return BUFFER_BIT_FRONT_LEFT; case GL_AUX0: return BUFFER_BIT_AUX0; case GL_AUX1: case GL_AUX2: case GL_AUX3: return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */ case GL_COLOR_ATTACHMENT0_EXT: return BUFFER_BIT_COLOR0; case GL_COLOR_ATTACHMENT1_EXT: return BUFFER_BIT_COLOR1; case GL_COLOR_ATTACHMENT2_EXT: return BUFFER_BIT_COLOR2; case GL_COLOR_ATTACHMENT3_EXT: return BUFFER_BIT_COLOR3; case GL_COLOR_ATTACHMENT4_EXT: return BUFFER_BIT_COLOR4; case GL_COLOR_ATTACHMENT5_EXT: return BUFFER_BIT_COLOR5; case GL_COLOR_ATTACHMENT6_EXT: return BUFFER_BIT_COLOR6; case GL_COLOR_ATTACHMENT7_EXT: return BUFFER_BIT_COLOR7; default: /* error */ return BAD_MASK; } }
void GLAPIENTRY _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *pixels ) { GLenum err = GL_NO_ERROR; struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); FLUSH_CURRENT(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n", width, height, _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type), pixels); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(width=%d height=%d)", width, height ); return; } if (ctx->NewState) _mesa_update_state(ctx); if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glReadPixels(incomplete framebuffer)" ); return; } rb = _mesa_get_read_renderbuffer_for_format(ctx, format); if (rb == NULL) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(read buffer)"); return; } /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the * combinations of format and type that can be used. * * Technically, only two combinations are actually allowed: * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal * preferred combination. This code doesn't know what that preferred * combination is, and Mesa can handle anything valid. Just work instead. */ if (_mesa_is_gles(ctx)) { if (ctx->API == API_OPENGLES2 && _mesa_is_color_format(format) && _mesa_get_color_read_format(ctx) == format && _mesa_get_color_read_type(ctx) == type) { err = GL_NO_ERROR; } else if (ctx->Version < 30) { err = _mesa_es_error_check_format_and_type(format, type, 2); if (err == GL_NO_ERROR) { if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) { err = GL_INVALID_OPERATION; } } } else { err = read_pixels_es3_error_check(format, type, rb); } if (err == GL_NO_ERROR && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)) { err = GL_INVALID_ENUM; } if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); return; } } err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); return; } if (_mesa_is_user_fbo(ctx->ReadBuffer) && ctx->ReadBuffer->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)"); return; } if (!_mesa_source_buffer_exists(ctx, format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)"); return; } /* Check that the destination format and source buffer are both * integer-valued or both non-integer-valued. */ if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) { const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format); const GLboolean dstInteger = _mesa_is_enum_format_integer(format); if (dstInteger != srcInteger) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(integer / non-integer format mismatch"); return; } } if (width == 0 || height == 0) return; /* nothing to do */ if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1, format, type, bufSize, pixels)) { if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(out of bounds PBO access)"); } else { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadnPixelsARB(out of bounds access:" " bufSize (%d) is too small)", bufSize); } return; } if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); return; } ctx->Driver.ReadPixels(ctx, x, y, width, height, format, type, &ctx->Pack, pixels); }
/** * Clear buffers. * * \param mask bit-mask indicating the buffers to be cleared. * * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin, * etc. If the rasterization mode is set to GL_RENDER then requests the driver * to clear the buffers, via the dd_function_table::Clear callback. */ void GLAPIENTRY _mesa_Clear( GLbitfield mask ) { GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); FLUSH_CURRENT(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glClear 0x%x\n", mask); if (mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT)) { /* invalid bit set */ _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); return; } /* Accumulation buffers were removed in core contexts, and they never * existed in OpenGL ES. */ if ((mask & GL_ACCUM_BUFFER_BIT) != 0 && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) { _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)"); return; } if (ctx->NewState) { _mesa_update_state( ctx ); /* update _Xmin, etc */ } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glClear(incomplete framebuffer)"); return; } if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 || ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax || ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax) return; if (ctx->RasterDiscard) return; if (ctx->RenderMode == GL_RENDER) { GLbitfield bufferMask; /* don't clear depth buffer if depth writing disabled */ if (!ctx->Depth.Mask) mask &= ~GL_DEPTH_BUFFER_BIT; /* Build the bitmask to send to device driver's Clear function. * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the * BUFFER_BIT_COLORn flags. */ bufferMask = 0; if (mask & GL_COLOR_BUFFER_BIT) { GLuint i; for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; if (buf >= 0) { bufferMask |= 1 << buf; } } } if ((mask & GL_DEPTH_BUFFER_BIT) && ctx->DrawBuffer->Visual.haveDepthBuffer) { bufferMask |= BUFFER_BIT_DEPTH; } if ((mask & GL_STENCIL_BUFFER_BIT) && ctx->DrawBuffer->Visual.haveStencilBuffer) { bufferMask |= BUFFER_BIT_STENCIL; } if ((mask & GL_ACCUM_BUFFER_BIT) && ctx->DrawBuffer->Visual.haveAccumBuffer) { bufferMask |= BUFFER_BIT_ACCUM; } ASSERT(ctx->Driver.Clear); ctx->Driver.Clear(ctx, bufferMask); } }
/** * Do error checking and update state for glVertex/Color/TexCoord/...Pointer * functions. * * \param func name of calling function used for error reporting * \param attrib the attribute array index to update * \param legalTypes bitmask of *_BIT above indicating legal datatypes * \param sizeMin min allowable size value * \param sizeMax max allowable size value (may also be BGRA_OR_4) * \param size components per element (1, 2, 3 or 4) * \param type datatype of each component (GL_FLOAT, GL_INT, etc) * \param stride stride between elements, in elements * \param normalized are integer types converted to floats in [-1, 1]? * \param integer integer-valued values (will not be normalized to [-1,1]) * \param ptr the address (or offset inside VBO) of the array data */ static void update_array(struct gl_context *ctx, const char *func, GLuint attrib, GLbitfield legalTypesMask, GLint sizeMin, GLint sizeMax, GLint size, GLenum type, GLsizei stride, GLboolean normalized, GLboolean integer, const GLvoid *ptr) { struct gl_client_array *array; GLbitfield typeBit; GLsizei elementSize; GLenum format = GL_RGBA; if (_mesa_is_gles(ctx)) { /* Once Mesa gets support for GL_OES_vertex_half_float this mask will * change. Adding support for this extension isn't quite as trivial as * we'd like because ES uses a different enum value for GL_HALF_FLOAT. */ legalTypesMask &= ~(FIXED_GL_BIT | HALF_BIT | DOUBLE_BIT); /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until * 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or * GL_OES_vertex_type_10_10_10_2. */ if (ctx->Version < 30) { legalTypesMask &= ~(UNSIGNED_INT_BIT | INT_BIT | UNSIGNED_INT_2_10_10_10_REV_BIT | INT_2_10_10_10_REV_BIT); } /* BGRA ordering is not supported in ES contexts. */ if (sizeMax == BGRA_OR_4) sizeMax = 4; } else { legalTypesMask &= ~FIXED_ES_BIT; if (!ctx->Extensions.ARB_ES2_compatibility) legalTypesMask &= ~FIXED_GL_BIT; if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT | INT_2_10_10_10_REV_BIT); } typeBit = type_to_bit(ctx, type); if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", func, _mesa_lookup_enum_by_nr(type)); return; } /* Do size parameter checking. * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and * must be handled specially. */ if (ctx->Extensions.EXT_vertex_array_bgra && sizeMax == BGRA_OR_4 && size == GL_BGRA) { GLboolean bgra_error = GL_FALSE; if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) { if (type != GL_UNSIGNED_INT_2_10_10_10_REV && type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_BYTE) bgra_error = GL_TRUE; } else if (type != GL_UNSIGNED_BYTE) bgra_error = GL_TRUE; if (bgra_error) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(GL_BGRA/GLubyte)", func); return; } format = GL_BGRA; size = 4; } else if (size < sizeMin || size > sizeMax || size > 4) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size); return; } if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev && (type == GL_UNSIGNED_INT_2_10_10_10_REV || type == GL_INT_2_10_10_10_REV) && size != 4) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); return; } ASSERT(size <= 4); if (stride < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride ); return; } if (ctx->Array.ArrayObj->ARBsemantics && !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) { /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs. * Generate GL_INVALID_OPERATION if that's not true. */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func); return; } elementSize = _mesa_sizeof_type(type) * size; array = &ctx->Array.ArrayObj->VertexAttrib[attrib]; array->Size = size; array->Type = type; array->Format = format; array->Stride = stride; array->StrideB = stride ? stride : elementSize; array->Normalized = normalized; array->Integer = integer; array->Ptr = (const GLubyte *) ptr; array->_ElementSize = elementSize; _mesa_reference_buffer_object(ctx, &array->BufferObj, ctx->Array.ArrayBufferObj); ctx->NewState |= _NEW_ARRAY; ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib); }
/** * Return list of (and count of) all specific texture compression * formats that are supported. * * Some formats are \b not returned by this function. The * \c GL_COMPRESSED_TEXTURE_FORMATS query only returns formats that are * "suitable for general-purpose usage." All texture compression extensions * have taken this to mean either linear RGB or linear RGBA. * * The GL_ARB_texture_compress_rgtc spec says: * * "19) Should the GL_NUM_COMPRESSED_TEXTURE_FORMATS and * GL_COMPRESSED_TEXTURE_FORMATS queries return the RGTC formats? * * RESOLVED: No. * * The OpenGL 2.1 specification says "The only values returned * by this query [GL_COMPRESSED_TEXTURE_FORMATS"] are those * corresponding to formats suitable for general-purpose usage. * The renderer will not enumerate formats with restrictions that * need to be specifically understood prior to use." * * Compressed textures with just red or red-green components are * not general-purpose so should not be returned by these queries * because they have restrictions. * * Applications that seek to use the RGTC formats should do so * by looking for this extension's name in the string returned by * glGetString(GL_EXTENSIONS) rather than * what GL_NUM_COMPRESSED_TEXTURE_FORMATS and * GL_COMPRESSED_TEXTURE_FORMATS return." * * There is nearly identical wording in the GL_EXT_texture_compression_rgtc * spec. * * The GL_EXT_texture_rRGB spec says: * * "22) Should the new COMPRESSED_SRGB_* formats be listed in an * implementation's GL_COMPRESSED_TEXTURE_FORMATS list? * * RESOLVED: No. Section 3.8.1 says formats listed by * GL_COMPRESSED_TEXTURE_FORMATS are "suitable for general-purpose * usage." The non-linear distribution of red, green, and * blue for these sRGB compressed formats makes them not really * general-purpose." * * The GL_EXT_texture_compression_latc spec says: * * "16) Should the GL_NUM_COMPRESSED_TEXTURE_FORMATS and * GL_COMPRESSED_TEXTURE_FORMATS queries return the LATC formats? * * RESOLVED: No. * * The OpenGL 2.1 specification says "The only values returned * by this query [GL_COMPRESSED_TEXTURE_FORMATS"] are those * corresponding to formats suitable for general-purpose usage. * The renderer will not enumerate formats with restrictions that * need to be specifically understood prior to use." * * Historically, OpenGL implementation have advertised the RGB and * RGBA versions of the S3TC extensions compressed format tokens * through this mechanism. * * The specification is not sufficiently clear about what "suitable * for general-purpose usage" means. Historically that seems to mean * unsigned RGB or unsigned RGBA. The DXT1 format supporting alpha * (GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) is not exposed in the list (at * least for NVIDIA drivers) because the alpha is always 1.0 expect * when it is 0.0 when RGB is required to be black. NVIDIA's even * limits itself to true linear RGB or RGBA formats, specifically * not including EXT_texture_sRGB's sRGB S3TC compressed formats. * * Adding luminance and luminance-alpha texture formats (and * certainly signed versions of luminance and luminance-alpha * formats!) invites potential comptaibility problems with old * applications using this mechanism since old applications are * unlikely to expect non-RGB or non-RGBA formats to be advertised * through this mechanism. However no specific misinteractions * with old applications is known. * * Applications that seek to use the LATC formats should do so * by looking for this extension's name in the string returned by * glGetString(GL_EXTENSIONS) rather than * what GL_NUM_COMPRESSED_TEXTURE_FORMATS and * GL_COMPRESSED_TEXTURE_FORMATS return." * * There is no formal spec for GL_ATI_texture_compression_3dc. Since the * formats added by this extension are luminance-alpha formats, it is * reasonable to expect them to follow the same rules as * GL_EXT_texture_compression_latc. At the very least, Catalyst 11.6 does not * expose the 3dc formats through this mechanism. * * The spec for GL_ARB_texture_compression_bptc doesn't mention whether it * should be included in GL_COMPRESSED_TEXTURE_FORMATS. However as it takes a * very long time to compress the textures in this format it's probably not * very useful as a general format where the GL will have to compress it on * the fly. * * \param ctx the GL context * \param formats the resulting format list (may be NULL). * * \return number of formats. */ GLuint _mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats) { GLint discard_formats[100]; GLuint n = 0; if (!formats) { formats = discard_formats; } if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.TDFX_texture_compression_FXT1) { formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX; formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX; } if (ctx->Extensions.EXT_texture_compression_s3tc) { formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; /* The ES and desktop GL specs diverge here. * * In desktop OpenGL, the driver can perform online compression of * uncompressed texture data. GL_NUM_COMPRESSED_TEXTURE_FORMATS and * GL_COMPRESSED_TEXTURE_FORMATS give the application a list of * formats that it could ask the driver to compress with some * expectation of quality. The GL_ARB_texture_compression spec * calls this "suitable for general-purpose usage." As noted * above, this means GL_COMPRESSED_RGBA_S3TC_DXT1_EXT is not * included in the list. * * In OpenGL ES, the driver never performs compression. * GL_NUM_COMPRESSED_TEXTURE_FORMATS and * GL_COMPRESSED_TEXTURE_FORMATS give the application a list of * formats that the driver can receive from the application. It * is the *complete* list of formats. The * GL_EXT_texture_compression_s3tc spec says: * * "New State for OpenGL ES 2.0.25 and 3.0.2 Specifications * * The queries for NUM_COMPRESSED_TEXTURE_FORMATS and * COMPRESSED_TEXTURE_FORMATS include * COMPRESSED_RGB_S3TC_DXT1_EXT, * COMPRESSED_RGBA_S3TC_DXT1_EXT, * COMPRESSED_RGBA_S3TC_DXT3_EXT, and * COMPRESSED_RGBA_S3TC_DXT5_EXT." * * Note that the addition is only to the OpenGL ES specification! */ if (_mesa_is_gles(ctx)) { formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; } } /* The GL_OES_compressed_ETC1_RGB8_texture spec says: * * "New State * * The queries for NUM_COMPRESSED_TEXTURE_FORMATS and * COMPRESSED_TEXTURE_FORMATS include ETC1_RGB8_OES." */ if (_mesa_is_gles(ctx) && ctx->Extensions.OES_compressed_ETC1_RGB8_texture) { formats[n++] = GL_ETC1_RGB8_OES; } if (ctx->API == API_OPENGLES) { formats[n++] = GL_PALETTE4_RGB8_OES; formats[n++] = GL_PALETTE4_RGBA8_OES; formats[n++] = GL_PALETTE4_R5_G6_B5_OES; formats[n++] = GL_PALETTE4_RGBA4_OES; formats[n++] = GL_PALETTE4_RGB5_A1_OES; formats[n++] = GL_PALETTE8_RGB8_OES; formats[n++] = GL_PALETTE8_RGBA8_OES; formats[n++] = GL_PALETTE8_R5_G6_B5_OES; formats[n++] = GL_PALETTE8_RGBA4_OES; formats[n++] = GL_PALETTE8_RGB5_A1_OES; } if (_mesa_is_gles3(ctx) || ctx->Extensions.ARB_ES3_compatibility) { formats[n++] = GL_COMPRESSED_RGB8_ETC2; formats[n++] = GL_COMPRESSED_RGBA8_ETC2_EAC; formats[n++] = GL_COMPRESSED_R11_EAC; formats[n++] = GL_COMPRESSED_RG11_EAC; formats[n++] = GL_COMPRESSED_SIGNED_R11_EAC; formats[n++] = GL_COMPRESSED_SIGNED_RG11_EAC; formats[n++] = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; } if (_mesa_is_gles3(ctx)) { formats[n++] = GL_COMPRESSED_SRGB8_ETC2; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; formats[n++] = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; } /* The KHR_texture_compression_astc_hdr spec says: * * "Interactions with OpenGL 4.2 * * OpenGL 4.2 supports the feature that compressed textures can be * compressed online, by passing the compressed texture format enum * as the internal format when uploading a texture using TexImage1D, * TexImage2D or TexImage3D (see Section 3.9.3, Texture Image * Specification, subsection Encoding of Special Internal Formats). * * Due to the complexity of the ASTC compression algorithm, it is * not usually suitable for online use, and therefore ASTC support * will be limited to pre-compressed textures only. Where on-device * compression is required, a domain-specific limited compressor * will typically be used, and this is therefore not suitable for * implementation in the driver. * * In particular, the ASTC format specifiers will not be added to * Table 3.14, and thus will not be accepted by the TexImage*D * functions, and will not be returned by the (already deprecated) * COMPRESSED_TEXTURE_FORMATS query." * * The ES and the desktop specs diverge here. In OpenGL ES, the * COMPRESSED_TEXTURE_FORMATS query returns the set of supported specific * compressed formats. */ if (ctx->API == API_OPENGLES2 && ctx->Extensions.KHR_texture_compression_astc_ldr) { formats[n++] = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_5x4_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_5x5_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_6x5_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_6x6_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_8x5_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_8x6_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_10x5_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_10x6_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_10x8_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_10x10_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_12x10_KHR; formats[n++] = GL_COMPRESSED_RGBA_ASTC_12x12_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR; } if (_mesa_is_gles3(ctx) && ctx->Extensions.OES_texture_compression_astc) { formats[n++] = GL_COMPRESSED_RGBA_ASTC_3x3x3_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_4x3x3_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_4x4x3_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_4x4x4_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_5x4x4_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_5x5x4_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_5x5x5_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_6x5x5_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_6x6x5_OES; formats[n++] = GL_COMPRESSED_RGBA_ASTC_6x6x6_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES; formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES; } assert(n <= ARRAY_SIZE(discard_formats)); return n; }
void GLAPIENTRY _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params) { struct gl_sampler_object *sampObj; GLuint res; GET_CURRENT_CONTEXT(ctx); sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states: * * "An INVALID_OPERATION error is generated if sampler is not the name * of a sampler object previously returned from a call to GenSamplers." * * In desktop GL, an GL_INVALID_VALUE is returned instead. */ _mesa_error(ctx, (_mesa_is_gles(ctx) ? GL_INVALID_OPERATION : GL_INVALID_VALUE), "glSamplerParameteriv(sampler %u)", sampler); return; } switch (pname) { case GL_TEXTURE_WRAP_S: res = set_sampler_wrap_s(ctx, sampObj, params[0]); break; case GL_TEXTURE_WRAP_T: res = set_sampler_wrap_t(ctx, sampObj, params[0]); break; case GL_TEXTURE_WRAP_R: res = set_sampler_wrap_r(ctx, sampObj, params[0]); break; case GL_TEXTURE_MIN_FILTER: res = set_sampler_min_filter(ctx, sampObj, params[0]); break; case GL_TEXTURE_MAG_FILTER: res = set_sampler_mag_filter(ctx, sampObj, params[0]); break; case GL_TEXTURE_MIN_LOD: res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]); break; case GL_TEXTURE_MAX_LOD: res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]); break; case GL_TEXTURE_LOD_BIAS: res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]); break; case GL_TEXTURE_COMPARE_MODE: res = set_sampler_compare_mode(ctx, sampObj, params[0]); break; case GL_TEXTURE_COMPARE_FUNC: res = set_sampler_compare_func(ctx, sampObj, params[0]); break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]); break; case GL_TEXTURE_CUBE_MAP_SEAMLESS: res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]); break; case GL_TEXTURE_SRGB_DECODE_EXT: res = set_sampler_srgb_decode(ctx, sampObj, params[0]); break; case GL_TEXTURE_BORDER_COLOR: { GLfloat c[4]; c[0] = INT_TO_FLOAT(params[0]); c[1] = INT_TO_FLOAT(params[1]); c[2] = INT_TO_FLOAT(params[2]); c[3] = INT_TO_FLOAT(params[3]); res = set_sampler_border_colorf(ctx, sampObj, c); } break; default: res = INVALID_PNAME; } switch (res) { case GL_FALSE: /* no change */ break; case GL_TRUE: /* state change - we do nothing special at this time */ break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n", _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n", params[0]); break; case INVALID_VALUE: _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n", params[0]); break; default: ; } }
void GLAPIENTRY _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) { struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states: * * "An INVALID_OPERATION error is generated if sampler is not the name * of a sampler object previously returned from a call to GenSamplers." * * In desktop GL, an GL_INVALID_VALUE is returned instead. */ _mesa_error(ctx, (_mesa_is_gles(ctx) ? GL_INVALID_OPERATION : GL_INVALID_VALUE), "glGetSamplerParameterfv(sampler %u)", sampler); return; } switch (pname) { case GL_TEXTURE_WRAP_S: *params = (GLfloat) sampObj->WrapS; break; case GL_TEXTURE_WRAP_T: *params = (GLfloat) sampObj->WrapT; break; case GL_TEXTURE_WRAP_R: *params = (GLfloat) sampObj->WrapR; break; case GL_TEXTURE_MIN_FILTER: *params = (GLfloat) sampObj->MinFilter; break; case GL_TEXTURE_MAG_FILTER: *params = (GLfloat) sampObj->MagFilter; break; case GL_TEXTURE_MIN_LOD: *params = sampObj->MinLod; break; case GL_TEXTURE_MAX_LOD: *params = sampObj->MaxLod; break; case GL_TEXTURE_LOD_BIAS: *params = sampObj->LodBias; break; case GL_TEXTURE_COMPARE_MODE: if (!ctx->Extensions.ARB_shadow) goto invalid_pname; *params = (GLfloat) sampObj->CompareMode; break; case GL_TEXTURE_COMPARE_FUNC: if (!ctx->Extensions.ARB_shadow) goto invalid_pname; *params = (GLfloat) sampObj->CompareFunc; break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: *params = sampObj->MaxAnisotropy; break; case GL_TEXTURE_BORDER_COLOR: params[0] = sampObj->BorderColor.f[0]; params[1] = sampObj->BorderColor.f[1]; params[2] = sampObj->BorderColor.f[2]; params[3] = sampObj->BorderColor.f[3]; break; case GL_TEXTURE_CUBE_MAP_SEAMLESS: if (!ctx->Extensions.AMD_seamless_cubemap_per_texture) goto invalid_pname; *params = (GLfloat) sampObj->CubeMapSeamless; break; case GL_TEXTURE_SRGB_DECODE_EXT: if (!ctx->Extensions.EXT_texture_sRGB_decode) goto invalid_pname; *params = (GLfloat) sampObj->sRGBDecode; break; default: goto invalid_pname; } return; invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)", _mesa_enum_to_string(pname)); }
/** * Test if an image format is a supported compressed format. * \param format the internal format token provided by the user. * \return GL_TRUE if compressed, GL_FALSE if uncompressed */ GLboolean _mesa_is_compressed_format(struct gl_context *ctx, GLenum format) { switch (format) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return ctx->Extensions.EXT_texture_compression_s3tc; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_compression_s3tc) || (ctx->API == API_OPENGLES2 && ctx->Extensions.ANGLE_texture_compression_dxt); case GL_RGB_S3TC: case GL_RGB4_S3TC: case GL_RGBA_S3TC: case GL_RGBA4_S3TC: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.S3_s3tc; case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_sRGB && ctx->Extensions.EXT_texture_compression_s3tc; case GL_COMPRESSED_RGB_FXT1_3DFX: case GL_COMPRESSED_RGBA_FXT1_3DFX: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.TDFX_texture_compression_FXT1; case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_SIGNED_RED_RGTC1: case GL_COMPRESSED_RG_RGTC2: case GL_COMPRESSED_SIGNED_RG_RGTC2: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_compression_rgtc; case GL_COMPRESSED_LUMINANCE_LATC1_EXT: case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_compression_latc; case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ATI_texture_compression_3dc; case GL_ETC1_RGB8_OES: return _mesa_is_gles(ctx) && ctx->Extensions.OES_compressed_ETC1_RGB8_texture; case GL_PALETTE4_RGB8_OES: case GL_PALETTE4_RGBA8_OES: case GL_PALETTE4_R5_G6_B5_OES: case GL_PALETTE4_RGBA4_OES: case GL_PALETTE4_RGB5_A1_OES: case GL_PALETTE8_RGB8_OES: case GL_PALETTE8_RGBA8_OES: case GL_PALETTE8_R5_G6_B5_OES: case GL_PALETTE8_RGBA4_OES: case GL_PALETTE8_RGB5_A1_OES: return ctx->API == API_OPENGLES; default: return GL_FALSE; } }
void _mesa_blit_framebuffer(struct gl_context *ctx, struct gl_framebuffer *readFb, struct gl_framebuffer *drawFb, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter, const char *func) { const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); FLUSH_VERTICES(ctx, 0); /* Update completeness status of readFb and drawFb. */ _mesa_update_framebuffer(ctx, readFb, drawFb); /* Make sure drawFb has an initialized bounding box. */ _mesa_update_draw_buffer_bounds(ctx, drawFb); if (!readFb || !drawFb) { /* This will normally never happen but someday we may want to * support MakeCurrent() with no drawables. */ return; } /* check for complete framebuffers */ if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "%s(incomplete draw/read buffers)", func); return; } if (!is_valid_blit_filter(ctx, filter)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func, _mesa_enum_to_string(filter)); return; } if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT || filter == GL_SCALED_RESOLVE_NICEST_EXT) && (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func, _mesa_enum_to_string(filter)); return; } if (mask & ~legalMaskBits) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func); return; } /* depth/stencil must be blitted with nearest filtering */ if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) && filter != GL_NEAREST) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(depth/stencil requires GL_NEAREST filter)", func); return; } /* get color read/draw renderbuffers */ if (mask & GL_COLOR_BUFFER_BIT) { const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers; const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if (!colorReadRb || numColorDrawBuffers == 0) { mask &= ~GL_COLOR_BUFFER_BIT; } else { for (i = 0; i < numColorDrawBuffers; i++) { colorDrawRb = drawFb->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL * ES 3.0.1 spec says: * * "If the source and destination buffers are identical, an * INVALID_OPERATION error is generated. Different mipmap * levels of a texture, different layers of a three- * dimensional texture or two-dimensional array texture, and * different faces of a cube map texture do not constitute * identical buffers." */ if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(source and destination color " "buffer cannot be the same)", func); return; } if (!compatible_color_datatypes(colorReadRb->Format, colorDrawRb->Format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(color buffer datatypes mismatch)", func); return; } /* extra checks for multisample copies... */ if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { /* color formats must match on GLES. This isn't checked on * desktop GL because the GL 4.4 spec was changed to allow it. * In the section entitled “Changes in the released * Specification of July 22, 2013” it says: * * “Relax BlitFramebuffer in section 18.3.1 so that format * conversion can take place during multisample blits, since * drivers already allow this and some apps depend on it.” */ if (_mesa_is_gles(ctx) && !compatible_resolve_formats(colorReadRb, colorDrawRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(bad src/dst multisample pixel formats)", func); return; } } } if (filter != GL_NEAREST) { /* From EXT_framebuffer_multisample_blit_scaled specification: * "Calling BlitFramebuffer will result in an INVALID_OPERATION error * if filter is not NEAREST and read buffer contains integer data." */ GLenum type = _mesa_get_format_datatype(colorReadRb->Format); if (type == GL_INT || type == GL_UNSIGNED_INT) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(integer color type)", func); return; } } } } if (mask & GL_STENCIL_BUFFER_BIT) { struct gl_renderbuffer *readRb = readFb->Attachment[BUFFER_STENCIL].Renderbuffer; struct gl_renderbuffer *drawRb = drawFb->Attachment[BUFFER_STENCIL].Renderbuffer; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_STENCIL_BUFFER_BIT; } else { int read_z_bits, draw_z_bits; if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(source and destination stencil " "buffer cannot be the same)", func); return; } if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { /* There is no need to check the stencil datatype here, because * there is only one: GL_UNSIGNED_INT. */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(stencil attachment format mismatch)", func); return; } read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS); draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS); /* If both buffers also have depth data, the depth formats must match * as well. If one doesn't have depth, it's not blitted, so we should * ignore the depth format check. */ if (read_z_bits > 0 && draw_z_bits > 0 && (read_z_bits != draw_z_bits || _mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(stencil attachment depth format mismatch)", func); return; } } } if (mask & GL_DEPTH_BUFFER_BIT) { struct gl_renderbuffer *readRb = readFb->Attachment[BUFFER_DEPTH].Renderbuffer; struct gl_renderbuffer *drawRb = drawFb->Attachment[BUFFER_DEPTH].Renderbuffer; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_DEPTH_BUFFER_BIT; } else { int read_s_bit, draw_s_bit; if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(source and destination depth " "buffer cannot be the same)", func); return; } if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || (_mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(depth attachment format mismatch)", func); return; } read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS); draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS); /* If both buffers also have stencil data, the stencil formats must * match as well. If one doesn't have stencil, it's not blitted, so * we should ignore the stencil format check. */ if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(depth attachment stencil bits mismatch)", func); return; } } } if (_mesa_is_gles3(ctx)) { /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES * 3.0.1 spec says: * * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero, * an INVALID_OPERATION error is generated." */ if (drawFb->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(destination samples must be 0)", func); return; } /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES * 3.0.1 spec says: * * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero, * no copy is performed and an INVALID_OPERATION error is generated * if the formats of the read and draw framebuffers are not * identical or if the source and destination rectangles are not * defined with the same (X0, Y0) and (X1, Y1) bounds." * * The format check was made above because desktop OpenGL has the same * requirement. */ if (readFb->Visual.samples > 0 && (srcX0 != dstX0 || srcY0 != dstY0 || srcX1 != dstX1 || srcY1 != dstY1)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(bad src/dst multisample region)", func); return; } } else { if (readFb->Visual.samples > 0 && drawFb->Visual.samples > 0 && readFb->Visual.samples != drawFb->Visual.samples) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(mismatched samples)", func); return; } /* extra checks for multisample copies... */ if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) && (filter == GL_NEAREST || filter == GL_LINEAR)) { /* src and dest region sizes must be the same */ if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) || abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(bad src/dst multisample region sizes)", func); return; } } } /* Debug code */ if (DEBUG_BLIT) { const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i = 0; printf("%s(%d, %d, %d, %d, %d, %d, %d, %d," " 0x%x, 0x%x)\n", func, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); if (colorReadRb) { const struct gl_renderbuffer_attachment *att; att = find_attachment(readFb, colorReadRb); printf(" Src FBO %u RB %u (%dx%d) ", readFb->Name, colorReadRb->Name, colorReadRb->Width, colorReadRb->Height); if (att && att->Texture) { printf("Tex %u tgt 0x%x level %u face %u", att->Texture->Name, att->Texture->Target, att->TextureLevel, att->CubeMapFace); } printf("\n"); /* Print all active color render buffers */ for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) { colorDrawRb = drawFb->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; att = find_attachment(drawFb, colorDrawRb); printf(" Dst FBO %u RB %u (%dx%d) ", drawFb->Name, colorDrawRb->Name, colorDrawRb->Width, colorDrawRb->Height); if (att && att->Texture) { printf("Tex %u tgt 0x%x level %u face %u", att->Texture->Name, att->Texture->Target, att->TextureLevel, att->CubeMapFace); } printf("\n"); } } } if (!mask || (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 || (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) { return; } assert(ctx->Driver.BlitFramebuffer); ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); }
/** * Choose an appropriate texture format given the format, type and * internalFormat parameters passed to glTexImage(). * * \param ctx the GL context. * \param internalFormat user's prefered internal texture format. * \param format incoming image pixel format. * \param type incoming image data type. * * \return a pointer to a gl_texture_format object which describes the * choosen texture format, or NULL on failure. * * This is called via dd_function_table::ChooseTextureFormat. Hardware drivers * will typically override this function with a specialized version. */ gl_format _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, GLint internalFormat, GLenum format, GLenum type) { (void) format; (void) type; switch (internalFormat) { /* shallow RGBA formats */ case 4: case GL_RGBA: if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) { RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); } else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) { RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555); } else if (type == GL_UNSIGNED_INT_2_10_10_10_REV) { RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB2101010); } RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; case GL_RGBA8: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; case GL_RGB5_A1: RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555); break; case GL_RGBA2: RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444_REV); /* just to test another format*/ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); break; case GL_RGBA4: RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); break; /* deep RGBA formats */ case GL_RGB10_A2: RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB2101010); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; case GL_RGBA12: case GL_RGBA16: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; /* shallow RGB formats */ case 3: case GL_RGB: if (type == GL_UNSIGNED_INT_2_10_10_10_REV) { RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB2101010); } /* fallthrough */ case GL_RGB8: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; case GL_R3_G3_B2: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB332); RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565_REV); RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; case GL_RGB4: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565_REV); /* just to test another format */ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); break; case GL_RGB5: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); break; /* deep RGB formats */ case GL_RGB10: case GL_RGB12: case GL_RGB16: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; /* Alpha formats */ case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: RETURN_IF_SUPPORTED(MESA_FORMAT_A8); break; case GL_ALPHA12: case GL_ALPHA16: RETURN_IF_SUPPORTED(MESA_FORMAT_A16); RETURN_IF_SUPPORTED(MESA_FORMAT_A8); break; /* Luminance formats */ case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: RETURN_IF_SUPPORTED(MESA_FORMAT_L8); break; case GL_LUMINANCE12: case GL_LUMINANCE16: RETURN_IF_SUPPORTED(MESA_FORMAT_L16); RETURN_IF_SUPPORTED(MESA_FORMAT_L8); break; /* Luminance/Alpha formats */ case GL_LUMINANCE4_ALPHA4: RETURN_IF_SUPPORTED(MESA_FORMAT_AL44); RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); break; case 2: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE6_ALPHA2: case GL_LUMINANCE8_ALPHA8: RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); break; case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: RETURN_IF_SUPPORTED(MESA_FORMAT_AL1616); RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); break; case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: RETURN_IF_SUPPORTED(MESA_FORMAT_I8); break; case GL_INTENSITY12: case GL_INTENSITY16: RETURN_IF_SUPPORTED(MESA_FORMAT_I16); RETURN_IF_SUPPORTED(MESA_FORMAT_I8); break; default: ; /* fallthrough */ } if (ctx->Extensions.ARB_depth_texture) { switch (internalFormat) { case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: RETURN_IF_SUPPORTED(MESA_FORMAT_Z32); RETURN_IF_SUPPORTED(MESA_FORMAT_X8_Z24); RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); break; case GL_DEPTH_COMPONENT16: RETURN_IF_SUPPORTED(MESA_FORMAT_Z16); RETURN_IF_SUPPORTED(MESA_FORMAT_X8_Z24); RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); default: ; /* fallthrough */ } } switch (internalFormat) { case GL_COMPRESSED_ALPHA_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_A8); break; case GL_COMPRESSED_LUMINANCE_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_L8); break; case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); break; case GL_COMPRESSED_INTENSITY_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_I8); break; case GL_COMPRESSED_RGB_ARB: /* We don't use texture compression for 1D and 1D array textures. * For 1D textures, compressions doesn't buy us much. * For 1D ARRAY textures, there's complicated issues with updating * sub-regions on non-block boundaries with glCopyTexSubImage, among * other issues. FWIW, the GL_EXT_texture_array extension prohibits * 1D ARRAY textures in S3TC format. */ if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) { if (ctx->Extensions.EXT_texture_compression_s3tc || ctx->Extensions.ANGLE_texture_compression_dxt) RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); if (ctx->Extensions.TDFX_texture_compression_FXT1) RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1); } RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; case GL_COMPRESSED_RGBA_ARB: /* We don't use texture compression for 1D and 1D array textures. */ if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) { if (ctx->Extensions.EXT_texture_compression_s3tc || ctx->Extensions.ANGLE_texture_compression_dxt) RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); /* Not rgba_dxt1, see spec */ if (ctx->Extensions.TDFX_texture_compression_FXT1) RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1); } RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; default: ; /* fallthrough */ } if (ctx->Extensions.ARB_ES2_compatibility) { switch (internalFormat) { case GL_RGB565: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); break; default: ; /* fallthrough */ } } if (ctx->Extensions.MESA_ycbcr_texture) { if (internalFormat == GL_YCBCR_MESA) { if (type == GL_UNSIGNED_SHORT_8_8_MESA) RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR); else RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR_REV); } } /* For non-generic compressed format we assert two things: * * 1. The format has already been validated against the set of available * extensions. * * 2. The driver only enables the extension if it supports all of the * formats that are part of that extension. */ switch (internalFormat) { case GL_COMPRESSED_RGB_FXT1_3DFX: return MESA_FORMAT_RGB_FXT1; case GL_COMPRESSED_RGBA_FXT1_3DFX: return MESA_FORMAT_RGBA_FXT1; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_RGB_S3TC: case GL_RGB4_S3TC: return MESA_FORMAT_RGB_DXT1; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return MESA_FORMAT_RGBA_DXT1; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_RGBA_S3TC: case GL_RGBA4_S3TC: return MESA_FORMAT_RGBA_DXT3; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return MESA_FORMAT_RGBA_DXT5; case GL_COMPRESSED_RED_RGTC1: return MESA_FORMAT_RED_RGTC1; case GL_COMPRESSED_SIGNED_RED_RGTC1: return MESA_FORMAT_SIGNED_RED_RGTC1; case GL_COMPRESSED_RG_RGTC2: return MESA_FORMAT_RG_RGTC2; case GL_COMPRESSED_SIGNED_RG_RGTC2: return MESA_FORMAT_SIGNED_RG_RGTC2; case GL_COMPRESSED_LUMINANCE_LATC1_EXT: return MESA_FORMAT_L_LATC1; case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: return MESA_FORMAT_SIGNED_L_LATC1; case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: return MESA_FORMAT_LA_LATC2; case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: return MESA_FORMAT_SIGNED_LA_LATC2; case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: return MESA_FORMAT_LA_LATC2; case GL_ETC1_RGB8_OES: return MESA_FORMAT_ETC1_RGB8; case GL_COMPRESSED_RGB8_ETC2: return MESA_FORMAT_ETC2_RGB8; case GL_COMPRESSED_SRGB8_ETC2: return MESA_FORMAT_ETC2_SRGB8; case GL_COMPRESSED_RGBA8_ETC2_EAC: return MESA_FORMAT_ETC2_RGBA8_EAC; case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: return MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC; case GL_COMPRESSED_R11_EAC: return MESA_FORMAT_ETC2_R11_EAC; case GL_COMPRESSED_RG11_EAC: return MESA_FORMAT_ETC2_RG11_EAC; case GL_COMPRESSED_SIGNED_R11_EAC: return MESA_FORMAT_ETC2_SIGNED_R11_EAC; case GL_COMPRESSED_SIGNED_RG11_EAC: return MESA_FORMAT_ETC2_SIGNED_RG11_EAC; case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: return MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1; case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1; case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: return MESA_FORMAT_SRGB_DXT1; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return MESA_FORMAT_SRGBA_DXT1; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return MESA_FORMAT_SRGBA_DXT3; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return MESA_FORMAT_SRGBA_DXT5; default: ; /* fallthrough */ } if (ctx->Extensions.ARB_texture_float) { switch (internalFormat) { case GL_ALPHA16F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); break; case GL_ALPHA32F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); break; case GL_LUMINANCE16F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); break; case GL_LUMINANCE32F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); break; case GL_LUMINANCE_ALPHA16F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); break; case GL_LUMINANCE_ALPHA32F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); break; case GL_INTENSITY16F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); break; case GL_INTENSITY32F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); break; case GL_RGB16F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); break; case GL_RGB32F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); break; case GL_RGBA16F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); break; case GL_RGBA32F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); break; default: ; /* fallthrough */ } } if (ctx->Extensions.EXT_texture_shared_exponent) { switch (internalFormat) { case GL_RGB9_E5: ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_RGB9_E5_FLOAT]); return MESA_FORMAT_RGB9_E5_FLOAT; default: ; /* fallthrough */ } } if (ctx->Extensions.EXT_packed_float) { switch (internalFormat) { case GL_R11F_G11F_B10F: ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_R11_G11_B10_FLOAT]); return MESA_FORMAT_R11_G11_B10_FLOAT; default: ; /* fallthrough */ } } if (ctx->Extensions.EXT_packed_depth_stencil) { switch (internalFormat) { case GL_DEPTH_STENCIL_EXT: case GL_DEPTH24_STENCIL8_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_S8); RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); break; default: ; /* fallthrough */ } } if (ctx->Extensions.ARB_depth_buffer_float) { switch (internalFormat) { case GL_DEPTH_COMPONENT32F: ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT]); return MESA_FORMAT_Z32_FLOAT; case GL_DEPTH32F_STENCIL8: ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT_X24S8]); return MESA_FORMAT_Z32_FLOAT_X24S8; default: ; /* fallthrough */ } } if (ctx->Extensions.ATI_envmap_bumpmap) { switch (internalFormat) { case GL_DUDV_ATI: case GL_DU8DV8_ATI: RETURN_IF_SUPPORTED(MESA_FORMAT_DUDV8); break; default: ; /* fallthrough */ } } if (ctx->Extensions.EXT_texture_snorm) { switch (internalFormat) { case GL_RED_SNORM: case GL_R8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R8); break; case GL_RG_SNORM: case GL_RG8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG88_REV); break; case GL_RGB_SNORM: case GL_RGB8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888); /* FALLTHROUGH */ case GL_RGBA_SNORM: case GL_RGBA8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_ALPHA_SNORM: case GL_ALPHA8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_A8); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_LUMINANCE_SNORM: case GL_LUMINANCE8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L8); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_LUMINANCE_ALPHA_SNORM: case GL_LUMINANCE8_ALPHA8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_AL88); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_INTENSITY_SNORM: case GL_INTENSITY8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_I8); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_R16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R16); break; case GL_RG16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_GR1616); break; case GL_RGB16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGB_16); /* FALLTHROUGH */ case GL_RGBA16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_ALPHA16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_A16); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_LUMINANCE16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L16); /* FALLTHROUGH */ case GL_LUMINANCE16_ALPHA16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_AL1616); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_INTENSITY16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_I16); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; default: ; /* fall-through */ } } if (ctx->Extensions.EXT_texture_sRGB) { switch (internalFormat) { case GL_SRGB_EXT: case GL_SRGB8_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8); RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); break; case GL_SRGB_ALPHA_EXT: case GL_SRGB8_ALPHA8_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8); RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); break; case GL_SLUMINANCE_EXT: case GL_SLUMINANCE8_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_SL8); RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); break; case GL_SLUMINANCE_ALPHA_EXT: case GL_SLUMINANCE8_ALPHA8_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8); RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); break; case GL_COMPRESSED_SLUMINANCE_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_SL8); RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); break; case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8); RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); break; case GL_COMPRESSED_SRGB_EXT: if (ctx->Extensions.EXT_texture_compression_s3tc) RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1); RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8); RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); break; case GL_COMPRESSED_SRGB_ALPHA_EXT: if (ctx->Extensions.EXT_texture_compression_s3tc) RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); /* Not srgba_dxt1, see spec */ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8); RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); break; default: ; /* fallthrough */ } } if (ctx->Extensions.EXT_texture_integer) { switch (internalFormat) { case GL_ALPHA8UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_UINT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8); break; case GL_ALPHA16UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_UINT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16); break; case GL_ALPHA32UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_UINT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32); break; case GL_ALPHA8I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_INT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8); break; case GL_ALPHA16I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_INT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16); break; case GL_ALPHA32I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_INT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32); break; case GL_LUMINANCE8UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_UINT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8); break; case GL_LUMINANCE16UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_UINT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16); break; case GL_LUMINANCE32UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_UINT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32); break; case GL_LUMINANCE8I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_INT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8); break; case GL_LUMINANCE16I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_INT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16); break; case GL_LUMINANCE32I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_INT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32); break; case GL_LUMINANCE_ALPHA8UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_UINT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8); break; case GL_LUMINANCE_ALPHA16UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_UINT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16); break; case GL_LUMINANCE_ALPHA32UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_UINT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32); break; case GL_LUMINANCE_ALPHA8I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_INT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8); break; case GL_LUMINANCE_ALPHA16I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_INT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16); break; case GL_LUMINANCE_ALPHA32I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_INT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32); break; case GL_INTENSITY8UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_UINT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8); break; case GL_INTENSITY16UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_UINT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16); break; case GL_INTENSITY32UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_UINT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32); break; case GL_INTENSITY8I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_INT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8); break; case GL_INTENSITY16I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_INT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16); break; case GL_INTENSITY32I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_INT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32); break; } } if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) { switch (internalFormat) { case GL_RGB8UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_UINT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8); break; case GL_RGB16UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_UINT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16); break; case GL_RGB32UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_UINT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32); break; case GL_RGB8I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_INT8); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8); break; case GL_RGB16I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_INT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16); break; case GL_RGB32I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_INT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32); break; case GL_RGBA8UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8); break; case GL_RGBA16UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16); break; case GL_RGBA32UI_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32); break; case GL_RGBA8I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8); break; case GL_RGBA16I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16); break; case GL_RGBA32I_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32); break; } } if (ctx->Extensions.ARB_texture_rg) { switch (internalFormat) { case GL_R8: case GL_RED: RETURN_IF_SUPPORTED(MESA_FORMAT_R8); break; case GL_COMPRESSED_RED: if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) RETURN_IF_SUPPORTED(MESA_FORMAT_RED_RGTC1); RETURN_IF_SUPPORTED(MESA_FORMAT_R8); break; case GL_R16: RETURN_IF_SUPPORTED(MESA_FORMAT_R16); break; case GL_RG: case GL_RG8: RETURN_IF_SUPPORTED(MESA_FORMAT_GR88); break; case GL_COMPRESSED_RG: if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) RETURN_IF_SUPPORTED(MESA_FORMAT_RG_RGTC2); RETURN_IF_SUPPORTED(MESA_FORMAT_GR88); break; case GL_RG16: RETURN_IF_SUPPORTED(MESA_FORMAT_GR1616); break; default: ; /* fallthrough */ } } if (ctx->Extensions.ARB_texture_rg && ctx->Extensions.ARB_texture_float) { switch (internalFormat) { case GL_R16F: RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); break; case GL_R32F: RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); break; case GL_RG16F: RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); break; case GL_RG32F: RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16); RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); break; default: ; /* fallthrough */ } } if (ctx->Version >= 30 || (ctx->Extensions.ARB_texture_rg && ctx->Extensions.EXT_texture_integer)) { switch (internalFormat) { case GL_R8UI: RETURN_IF_SUPPORTED(MESA_FORMAT_R_UINT8); break; case GL_RG8UI: RETURN_IF_SUPPORTED(MESA_FORMAT_RG_UINT8); break; case GL_R16UI: RETURN_IF_SUPPORTED(MESA_FORMAT_R_UINT16); break; case GL_RG16UI: RETURN_IF_SUPPORTED(MESA_FORMAT_RG_UINT16); break; case GL_R32UI: RETURN_IF_SUPPORTED(MESA_FORMAT_R_UINT32); break; case GL_RG32UI: RETURN_IF_SUPPORTED(MESA_FORMAT_RG_UINT32); break; case GL_R8I: RETURN_IF_SUPPORTED(MESA_FORMAT_R_INT8); break; case GL_RG8I: RETURN_IF_SUPPORTED(MESA_FORMAT_RG_INT8); break; case GL_R16I: RETURN_IF_SUPPORTED(MESA_FORMAT_R_INT16); break; case GL_RG16I: RETURN_IF_SUPPORTED(MESA_FORMAT_RG_INT16); break; case GL_R32I: RETURN_IF_SUPPORTED(MESA_FORMAT_R_INT32); break; case GL_RG32I: RETURN_IF_SUPPORTED(MESA_FORMAT_RG_INT32); break; default: break; } } if (ctx->Extensions.ARB_texture_rgb10_a2ui) { switch (internalFormat) { case GL_RGB10_A2UI: RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB2101010_UINT); RETURN_IF_SUPPORTED(MESA_FORMAT_ABGR2101010_UINT); break; default: break; } } /* GL_BGRA can be an internal format *only* in OpenGL ES (1.x or 2.0). */ if (_mesa_is_gles(ctx)) { switch (internalFormat) { case GL_BGRA: RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); break; default: ; /* fallthrough */ } } _mesa_problem(ctx, "unexpected format %s in _mesa_choose_tex_format()", _mesa_lookup_enum_by_nr(internalFormat)); return MESA_FORMAT_NONE; }
static bool compressed_format_compatible(const struct gl_context *ctx, GLenum compressedFormat, GLenum otherFormat) { enum mesa_block_class compressedClass, otherClass; /* Two view-incompatible compressed formats are never compatible. */ if (_mesa_is_compressed_format(ctx, otherFormat)) { return false; } /* * From ARB_copy_image spec: * Table 4.X.1 (Compatible internal formats for copying between * compressed and uncompressed internal formats) * --------------------------------------------------------------------- * | Texel / | Uncompressed | | * | Block | internal format | Compressed internal format | * | size | | | * --------------------------------------------------------------------- * | 128-bit | RGBA32UI, | COMPRESSED_RGBA_S3TC_DXT3_EXT, | * | | RGBA32I, | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,| * | | RGBA32F | COMPRESSED_RGBA_S3TC_DXT5_EXT, | * | | | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,| * | | | COMPRESSED_RG_RGTC2, | * | | | COMPRESSED_SIGNED_RG_RGTC2, | * | | | COMPRESSED_RGBA_BPTC_UNORM, | * | | | COMPRESSED_SRGB_ALPHA_BPTC_UNORM, | * | | | COMPRESSED_RGB_BPTC_SIGNED_FLOAT, | * | | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT | * --------------------------------------------------------------------- * | 64-bit | RGBA16F, RG32F, | COMPRESSED_RGB_S3TC_DXT1_EXT, | * | | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT, | * | | RGBA16I, RG32I, | COMPRESSED_RGBA_S3TC_DXT1_EXT, | * | | RGBA16, | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,| * | | RGBA16_SNORM | COMPRESSED_RED_RGTC1, | * | | | COMPRESSED_SIGNED_RED_RGTC1 | * --------------------------------------------------------------------- */ switch (compressedFormat) { case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: case GL_COMPRESSED_RG_RGTC2: case GL_COMPRESSED_SIGNED_RG_RGTC2: case GL_COMPRESSED_RGBA_BPTC_UNORM: case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: compressedClass = BLOCK_CLASS_128_BITS; break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_SIGNED_RED_RGTC1: compressedClass = BLOCK_CLASS_64_BITS; break; case GL_COMPRESSED_RGBA8_ETC2_EAC: case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: case GL_COMPRESSED_RG11_EAC: case GL_COMPRESSED_SIGNED_RG11_EAC: if (_mesa_is_gles(ctx)) compressedClass = BLOCK_CLASS_128_BITS; else return false; break; case GL_COMPRESSED_RGB8_ETC2: case GL_COMPRESSED_SRGB8_ETC2: case GL_COMPRESSED_R11_EAC: case GL_COMPRESSED_SIGNED_R11_EAC: case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: if (_mesa_is_gles(ctx)) compressedClass = BLOCK_CLASS_64_BITS; else return false; break; default: if (_mesa_is_gles(ctx) && _mesa_is_astc_format(compressedFormat)) compressedClass = BLOCK_CLASS_128_BITS; else return false; break; } switch (otherFormat) { case GL_RGBA32UI: case GL_RGBA32I: case GL_RGBA32F: otherClass = BLOCK_CLASS_128_BITS; break; case GL_RGBA16F: case GL_RG32F: case GL_RGBA16UI: case GL_RG32UI: case GL_RGBA16I: case GL_RG32I: case GL_RGBA16: case GL_RGBA16_SNORM: otherClass = BLOCK_CLASS_64_BITS; break; default: return false; } return compressedClass == otherClass; }