* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
*/
#include "texobj.h"
#include "texstate.h"
#include "texstorage.h"
+#include "textureview.h"
#include "mtypes.h"
#include "glformats.h"
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
return GL_DEPTH_COMPONENT;
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH24_STENCIL8:
+ return GL_DEPTH_STENCIL;
default:
; /* fallthrough */
}
default:
; /* fallthrough */
}
-
+
if (ctx->Extensions.TDFX_texture_compression_FXT1) {
switch (internalFormat) {
case GL_COMPRESSED_RGB_FXT1_3DFX:
}
}
- if (ctx->Extensions.EXT_packed_depth_stencil) {
- switch (internalFormat) {
- case GL_DEPTH_STENCIL_EXT:
- case GL_DEPTH24_STENCIL8_EXT:
- return GL_DEPTH_STENCIL_EXT;
- default:
- ; /* fallthrough */
- }
- }
-
if (ctx->Extensions.EXT_texture_sRGB) {
switch (internalFormat) {
case GL_SRGB_EXT:
case GL_SRGB8_EXT:
case GL_COMPRESSED_SRGB_EXT:
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
return GL_RGB;
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return ctx->Extensions.EXT_texture_compression_s3tc ? GL_RGB : -1;
case GL_SRGB_ALPHA_EXT:
case GL_SRGB8_ALPHA8_EXT:
case GL_COMPRESSED_SRGB_ALPHA_EXT:
+ return GL_RGBA;
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 GL_RGBA;
+ return ctx->Extensions.EXT_texture_compression_s3tc ? GL_RGBA : -1;
case GL_SLUMINANCE_ALPHA_EXT:
case GL_SLUMINANCE8_ALPHA8_EXT:
case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
if (ctx->Extensions.ARB_texture_rg) {
switch (internalFormat) {
case GL_R16F:
- /* R16F depends on both ARB_half_float_pixel and ARB_texture_float.
- */
- if (!ctx->Extensions.ARB_half_float_pixel)
- break;
- /* FALLTHROUGH */
case GL_R32F:
if (!ctx->Extensions.ARB_texture_float)
break;
return GL_RED;
case GL_RG16F:
- /* RG16F depends on both ARB_half_float_pixel and ARB_texture_float.
- */
- if (!ctx->Extensions.ARB_half_float_pixel)
- break;
- /* FALLTHROUGH */
case GL_RG32F:
if (!ctx->Extensions.ARB_texture_float)
break;
/**
* Allocate a texture image structure.
- *
+ *
* Called via ctx->Driver.NewTextureImage() unless overriden by a device
* driver.
*
GLboolean
_mesa_is_proxy_texture(GLenum target)
{
+ unsigned i;
+ static const GLenum targets[] = {
+ GL_PROXY_TEXTURE_1D,
+ GL_PROXY_TEXTURE_2D,
+ GL_PROXY_TEXTURE_3D,
+ GL_PROXY_TEXTURE_CUBE_MAP,
+ GL_PROXY_TEXTURE_RECTANGLE,
+ GL_PROXY_TEXTURE_1D_ARRAY,
+ GL_PROXY_TEXTURE_2D_ARRAY,
+ GL_PROXY_TEXTURE_CUBE_MAP_ARRAY,
+ GL_PROXY_TEXTURE_2D_MULTISAMPLE,
+ GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY
+ };
/*
- * NUM_TEXTURE_TARGETS should match number of terms below, except there's no
+ * NUM_TEXTURE_TARGETS should match number of terms above, except there's no
* proxy for GL_TEXTURE_BUFFER and GL_TEXTURE_EXTERNAL_OES.
*/
- assert(NUM_TEXTURE_TARGETS == 10 + 2);
-
- return (target == GL_PROXY_TEXTURE_1D ||
- target == GL_PROXY_TEXTURE_2D ||
- target == GL_PROXY_TEXTURE_3D ||
- target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
- target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
- target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
- target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
- target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY ||
- target == GL_PROXY_TEXTURE_2D_MULTISAMPLE ||
- target == GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY);
+ STATIC_ASSERT(NUM_TEXTURE_TARGETS == Elements(targets) + 2);
+
+ for (i = 0; i < Elements(targets); ++i)
+ if (target == targets[i])
+ return GL_TRUE;
+ return GL_FALSE;
}
/**
* Return the proxy target which corresponds to the given texture target
*/
-GLenum
-_mesa_get_proxy_target(GLenum target)
+static GLenum
+proxy_target(GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
return GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY;
default:
- _mesa_problem(NULL, "unexpected target in _mesa_get_proxy_target()");
+ _mesa_problem(NULL, "unexpected target in proxy_target()");
return 0;
}
}
/**
- * Get the texture object that corresponds to the target of the given
- * texture unit. The target should have already been checked for validity.
- *
- * \param ctx GL context.
- * \param texUnit texture unit.
- * \param target texture target.
- *
- * \return pointer to the texture object on success, or NULL on failure.
+ * Return a pointer to the current texture object for the given target
+ * on the current texture unit.
+ * Note: all <target> error checking should have been done by this point.
*/
struct gl_texture_object *
-_mesa_select_tex_object(struct gl_context *ctx,
- const struct gl_texture_unit *texUnit,
- GLenum target)
+_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target)
{
- const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ const GLboolean arrayTex = ctx->Extensions.EXT_texture_array;
switch (target) {
case GL_TEXTURE_1D:
ctx->Extensions.ARB_texture_buffer_object ?
texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL;
case GL_TEXTURE_EXTERNAL_OES:
- return ctx->Extensions.OES_EGL_image_external
+ return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL;
case GL_TEXTURE_2D_MULTISAMPLE:
return ctx->Extensions.ARB_texture_multisample
return ctx->Extensions.ARB_texture_multisample
? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
default:
- _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
+ _mesa_problem(NULL, "bad target in _mesa_get_current_tex_object()");
return NULL;
}
}
-/**
- * Return pointer to texture object for given target on current texture unit.
- */
-struct gl_texture_object *
-_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target)
-{
- struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
- return _mesa_select_tex_object(ctx, texUnit, target);
-}
-
/**
* Get a texture image pointer from a texture object, given a texture
if (!texObj)
return NULL;
-
+
texImage = _mesa_select_tex_image(ctx, texObj, target, level);
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
*
* \param ctx GL context.
* \param target texture target.
- *
+ *
* \return the maximum number of allowed mipmap levels for the given
* texture target, or zero if passed a bad target.
*
case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
case GL_TEXTURE_2D_ARRAY_EXT:
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- return (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array)
+ return ctx->Extensions.EXT_texture_array
? ctx->Const.MaxTextureLevels : 0;
case GL_TEXTURE_CUBE_MAP_ARRAY:
case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
}
+/**
+ * Check if a texture target can have more than one layer.
+ */
+GLboolean
+_mesa_tex_target_is_layered(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE:
+ case GL_PROXY_TEXTURE_RECTANGLE:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_BUFFER:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ case GL_TEXTURE_EXTERNAL_OES:
+ return GL_FALSE;
+
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_PROXY_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_PROXY_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ return GL_TRUE;
+
+ default:
+ assert(!"Invalid texture target.");
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Return the number of layers present in the given level of an array,
+ * cubemap or 3D texture. If the texture is not layered return zero.
+ */
+GLuint
+_mesa_get_texture_layers(const struct gl_texture_object *texObj, GLint level)
+{
+ assert(level >= 0 && level < MAX_TEXTURE_LEVELS);
+
+ switch (texObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_BUFFER:
+ case GL_TEXTURE_EXTERNAL_OES:
+ return 0;
+
+ case GL_TEXTURE_CUBE_MAP:
+ return 6;
+
+ case GL_TEXTURE_1D_ARRAY: {
+ struct gl_texture_image *img = texObj->Image[0][level];
+ return img ? img->Height : 0;
+ }
+
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
+ struct gl_texture_image *img = texObj->Image[0][level];
+ return img ? img->Depth : 0;
+ }
+
+ default:
+ assert(!"Invalid texture target.");
+ return 0;
+ }
+}
+
+
/**
* Return the maximum number of mipmap levels for the given target
* and the dimensions.
switch (target) {
case GL_TEXTURE_1D:
case GL_TEXTURE_1D_ARRAY:
+ case GL_PROXY_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D_ARRAY:
size = width;
break;
case GL_TEXTURE_CUBE_MAP:
case GL_TEXTURE_CUBE_MAP_ARRAY:
- ASSERT(width == height);
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
size = width;
break;
case GL_TEXTURE_2D:
case GL_TEXTURE_2D_ARRAY:
+ case GL_PROXY_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D_ARRAY:
size = MAX2(width, height);
break;
case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
size = MAX3(width, height, depth);
break;
case GL_TEXTURE_RECTANGLE:
case GL_TEXTURE_EXTERNAL_OES:
case GL_TEXTURE_2D_MULTISAMPLE:
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ case GL_PROXY_TEXTURE_RECTANGLE:
+ case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
+ case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
return 1;
default:
assert(0);
* \param border image border.
* \param internalFormat internal format.
* \param format the actual hardware format (one of MESA_FORMAT_*)
+ * \param numSamples number of samples per texel, or zero for non-MS.
+ * \param fixedSampleLocations are sample locations fixed?
*
* Fills in the fields of \p img with the given information.
* Note: width, height and depth include the border.
*/
-void
-_mesa_init_teximage_fields(struct gl_context *ctx,
- struct gl_texture_image *img,
- GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLenum internalFormat,
- gl_format format)
+static void
+init_teximage_fields_ms(struct gl_context *ctx,
+ struct gl_texture_image *img,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum internalFormat,
+ mesa_format format,
+ GLuint numSamples, GLboolean fixedSampleLocations)
{
GLenum target;
ASSERT(img);
_mesa_get_tex_max_num_levels(target,
img->Width2, img->Height2, img->Depth2);
img->TexFormat = format;
+ img->NumSamples = numSamples;
+ img->FixedSampleLocations = fixedSampleLocations;
+}
+
+
+void
+_mesa_init_teximage_fields(struct gl_context *ctx,
+ struct gl_texture_image *img,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum internalFormat,
+ mesa_format format)
+{
+ init_teximage_fields_ms(ctx, img, width, height, depth, border,
+ internalFormat, format, 0, GL_TRUE);
}
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
maxSize >>= level;
+ if (width != height)
+ return GL_FALSE;
if (width < 2 * border || width > 2 * border + maxSize)
return GL_FALSE;
if (height < 2 * border || height > 2 * border + maxSize)
return GL_FALSE;
if (height < 2 * border || height > 2 * border + maxSize)
return GL_FALSE;
- if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers)
+ if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers)
return GL_FALSE;
if (!ctx->Extensions.ARB_texture_non_power_of_two) {
if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
return GL_FALSE;
if (height < 2 * border || height > 2 * border + maxSize)
return GL_FALSE;
- if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers)
+ if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers || depth % 6)
+ return GL_FALSE;
+ if (width != height)
return GL_FALSE;
if (level >= ctx->Const.MaxCubeTextureLevels)
return GL_FALSE;
}
/* check xoffset and width */
- if (xoffset < -destImage->Border) {
+ if (xoffset < - (GLint) destImage->Border) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset)",
function, dims);
return GL_TRUE;
}
- if (xoffset + subWidth > destImage->Width) {
+ if (xoffset + subWidth > (GLint) destImage->Width) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset+width)",
function, dims);
return GL_TRUE;
function, dims);
return GL_TRUE;
}
- if (yoffset + subHeight > destImage->Height) {
+ if (yoffset + subHeight > (GLint) destImage->Height) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(yoffset+height)",
function, dims);
return GL_TRUE;
/* check zoffset and depth */
if (dims > 2) {
- GLint zBorder = (target == GL_TEXTURE_2D_ARRAY) ? 0 : destImage->Border;
+ GLint zBorder = (target == GL_TEXTURE_2D_ARRAY ||
+ target == GL_TEXTURE_CUBE_MAP_ARRAY) ?
+ 0 : destImage->Border;
+
if (zoffset < -zBorder) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s3D(zoffset)", function);
return GL_TRUE;
return GL_TRUE;
}
- /* size must be multiple of bw by bh or equal to whole texture size */
- if ((subWidth % bw != 0) && subWidth != destImage->Width) {
+ /* The size must be a multiple of bw x bh, or we must be using a
+ * offset+size that exactly hits the edge of the image. This
+ * is important for small mipmap levels (1x1, 2x1, etc) and for
+ * NPOT textures.
+ */
+ if ((subWidth % bw != 0) &&
+ (xoffset + subWidth != (GLint) destImage->Width)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s%dD(width = %d)", function, dims, subWidth);
return GL_TRUE;
}
- if ((subHeight % bh != 0) && subHeight != destImage->Height) {
+ if ((subHeight % bh != 0) &&
+ (yoffset + subHeight != (GLint) destImage->Height)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s%dD(height = %d)", function, dims, subHeight);
return GL_TRUE;
- }
+ }
}
return GL_FALSE;
*/
GLboolean
_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
- gl_format format,
+ mesa_format format,
GLint width, GLint height, GLint depth, GLint border)
{
/* We just check if the image size is less than MaxTextureMbytes.
return ctx->Extensions.ARB_texture_cube_map;
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
case GL_TEXTURE_2D_ARRAY_EXT:
- return (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
+ return ctx->Extensions.EXT_texture_array;
case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
case GL_TEXTURE_CUBE_MAP_ARRAY:
return ctx->Extensions.ARB_texture_cube_map_array;
default:
return GL_FALSE;
- }
+ }
}
&& ctx->Extensions.NV_texture_rectangle;
case GL_TEXTURE_1D_ARRAY_EXT:
case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- return _mesa_is_desktop_gl(ctx)
- && (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
+ return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
default:
return GL_FALSE;
}
case GL_PROXY_TEXTURE_3D:
return _mesa_is_desktop_gl(ctx);
case GL_TEXTURE_2D_ARRAY_EXT:
- return (_mesa_is_desktop_gl(ctx)
- && (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array))
+ return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
|| _mesa_is_gles3(ctx);
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- return _mesa_is_desktop_gl(ctx)
- && (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
+ return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
case GL_TEXTURE_CUBE_MAP_ARRAY:
case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
return ctx->Extensions.ARB_texture_cube_map_array;
return _mesa_is_desktop_gl(ctx)
&& ctx->Extensions.NV_texture_rectangle;
case GL_TEXTURE_1D_ARRAY_EXT:
- return _mesa_is_desktop_gl(ctx)
- && (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
+ return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
default:
return GL_FALSE;
}
case GL_TEXTURE_3D:
return GL_TRUE;
case GL_TEXTURE_2D_ARRAY_EXT:
- return (_mesa_is_desktop_gl(ctx)
- && (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array))
+ return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
|| _mesa_is_gles3(ctx);
case GL_TEXTURE_CUBE_MAP_ARRAY:
case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
static GLboolean
mutable_tex_object(struct gl_context *ctx, GLenum target)
{
- if (ctx->Extensions.ARB_texture_storage) {
- struct gl_texture_object *texObj =
- _mesa_get_current_tex_object(ctx, target);
- return !texObj->Immutable;
- }
- return GL_TRUE;
+ struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
+ return !texObj->Immutable;
}
compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
GLenum glformat)
{
- gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
+ mesa_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
return _mesa_format_image_size(mesaFormat, width, height, depth);
}
+/**
+ * Verify that a texture format is valid with a particular target
+ *
+ * In particular, textures with base format of \c GL_DEPTH_COMPONENT or
+ * \c GL_DEPTH_STENCIL are only valid with certain, context dependent texture
+ * targets.
+ *
+ * \param ctx GL context
+ * \param target Texture target
+ * \param internalFormat Internal format of the texture image
+ * \param dimensions Dimensionality at the caller. This is \b not used
+ * in the validation. It is only used when logging
+ * error messages.
+ * \param caller Base name of the calling function (e.g.,
+ * "glTexImage" or "glTexStorage").
+ *
+ * \returns true if the combination is legal, false otherwise.
+ */
+bool
+_mesa_legal_texture_base_format_for_target(struct gl_context *ctx,
+ GLenum target, GLenum internalFormat,
+ unsigned dimensions,
+ const char *caller)
+{
+ if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT
+ || _mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_STENCIL) {
+ /* Section 3.8.3 (Texture Image Specification) of the OpenGL 3.3 Core
+ * Profile spec says:
+ *
+ * "Textures with a base internal format of DEPTH_COMPONENT or
+ * DEPTH_STENCIL are supported by texture image specification
+ * commands only if target is TEXTURE_1D, TEXTURE_2D,
+ * TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_RECTANGLE,
+ * TEXTURE_CUBE_MAP, PROXY_TEXTURE_1D, PROXY_TEXTURE_2D,
+ * PROXY_TEXTURE_1D_ARRAY, PROXY_TEXTURE_2D_ARRAY,
+ * PROXY_TEXTURE_RECTANGLE, or PROXY_TEXTURE_CUBE_MAP. Using these
+ * formats in conjunction with any other target will result in an
+ * INVALID_OPERATION error."
+ *
+ * Cubemaps are only supported with desktop OpenGL version >= 3.0,
+ * EXT_gpu_shader4, or, on OpenGL ES 2.0+, OES_depth_texture_cube_map.
+ */
+ if (target != GL_TEXTURE_1D &&
+ target != GL_PROXY_TEXTURE_1D &&
+ target != GL_TEXTURE_2D &&
+ target != GL_PROXY_TEXTURE_2D &&
+ target != GL_TEXTURE_1D_ARRAY &&
+ target != GL_PROXY_TEXTURE_1D_ARRAY &&
+ target != GL_TEXTURE_2D_ARRAY &&
+ target != GL_PROXY_TEXTURE_2D_ARRAY &&
+ target != GL_TEXTURE_RECTANGLE_ARB &&
+ target != GL_PROXY_TEXTURE_RECTANGLE_ARB &&
+ !((_mesa_is_cube_face(target) ||
+ target == GL_TEXTURE_CUBE_MAP ||
+ target == GL_PROXY_TEXTURE_CUBE_MAP) &&
+ (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4
+ || (ctx->API == API_OPENGLES2 && ctx->Extensions.OES_depth_texture_cube_map))) &&
+ !((target == GL_TEXTURE_CUBE_MAP_ARRAY ||
+ target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) &&
+ ctx->Extensions.ARB_texture_cube_map_array)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s%dD(bad target for depth texture)",
+ caller, dimensions);
+ return false;
+ }
+ }
+
+ return true;
+}
/**
* Test the glTexImage[123]D() parameters for errors.
- *
+ *
* \param ctx GL context.
* \param dimensions texture image dimensions (must be 1, 2 or 3).
* \param target texture target given by the user (already validated).
* \param height image height given by the user.
* \param depth image depth given by the user.
* \param border image border given by the user.
- *
+ *
* \return GL_TRUE if a error is found, GL_FALSE otherwise
*
* Verifies each of the parameters against the constants specified in
GLint depth, GLint border )
{
GLboolean colorFormat;
+ GLboolean is_format_depth_or_depthstencil;
+ GLboolean is_internalFormat_depth_or_depthstencil;
GLenum err;
/* Even though there are no color-index textures, we still have to support
internalFormat);
} else {
if (format != internalFormat) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexImage%dD(format = %s, internalFormat = %s)",
- dimensions,
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(internalFormat));
- return GL_TRUE;
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage%dD(format = %s, internalFormat = %s)",
+ dimensions,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(internalFormat));
+ return GL_TRUE;
}
err = _mesa_es_error_check_format_and_type(format, type, dimensions);
}
}
- if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
- _mesa_is_cube_face(target)) && width != height) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage2D(cube width != height)");
- return GL_TRUE;
- }
-
- if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY ||
- target == GL_TEXTURE_CUBE_MAP_ARRAY) && width != height) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage3D(cube array width != height)");
- return GL_TRUE;
- }
-
- if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY ||
- target == GL_TEXTURE_CUBE_MAP_ARRAY) && (depth % 6)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage3D(cube array depth not multiple of 6)");
- return GL_TRUE;
- }
-
/* Check internalFormat */
if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
}
/* make sure internal format and format basically agree */
+ is_internalFormat_depth_or_depthstencil =
+ _mesa_is_depth_format(internalFormat) ||
+ _mesa_is_depthstencil_format(internalFormat);
+
+ is_format_depth_or_depthstencil =
+ _mesa_is_depth_format(format) ||
+ _mesa_is_depthstencil_format(format);
+
colorFormat = _mesa_is_color_format(format);
if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
- (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) ||
+ (is_internalFormat_depth_or_depthstencil != is_format_depth_or_depthstencil) ||
(_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) ||
- (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) ||
(_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glTexImage%dD(incompatible internalFormat = %s, format = %s)",
}
/* additional checks for depth textures */
- if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT
- || _mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_STENCIL) {
- /* Only 1D, 2D, rect, array and cube textures supported, not 3D
- * Cubemaps are only supported for GL version > 3.0 or with EXT_gpu_shader4 */
- if (target != GL_TEXTURE_1D &&
- target != GL_PROXY_TEXTURE_1D &&
- target != GL_TEXTURE_2D &&
- target != GL_PROXY_TEXTURE_2D &&
- target != GL_TEXTURE_1D_ARRAY &&
- target != GL_PROXY_TEXTURE_1D_ARRAY &&
- target != GL_TEXTURE_2D_ARRAY &&
- target != GL_PROXY_TEXTURE_2D_ARRAY &&
- target != GL_TEXTURE_RECTANGLE_ARB &&
- target != GL_PROXY_TEXTURE_RECTANGLE_ARB &&
- !((_mesa_is_cube_face(target) || target == GL_PROXY_TEXTURE_CUBE_MAP) &&
- (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4
- || (ctx->API == API_OPENGLES2 && ctx->Extensions.OES_depth_texture_cube_map))) &&
- !((target == GL_TEXTURE_CUBE_MAP_ARRAY ||
- target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) &&
- ctx->Extensions.ARB_texture_cube_map_array)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexImage%dD(bad target for depth texture)",
- dimensions);
- return GL_TRUE;
- }
- }
+ if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalFormat,
+ dimensions, "glTexImage"))
+ return GL_TRUE;
/* additional checks for compressed textures */
if (_mesa_is_compressed_format(ctx, internalFormat)) {
/* This will detect any invalid internalFormat value */
if (!_mesa_is_compressed_format(ctx, internalFormat)) {
- reason = "internalFormat";
- error = GL_INVALID_ENUM;
- goto error;
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCompressedTexImage%dD(internalFormat=%s)",
+ dimensions, _mesa_lookup_enum_by_nr(internalFormat));
+ return GL_TRUE;
}
switch (internalFormat) {
goto error;
}
- /* For cube map, width must equal height */
- if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
- _mesa_is_cube_face(target)) && width != height) {
- reason = "width != height";
- error = GL_INVALID_VALUE;
- goto error;
- }
-
/* check image size in bytes */
if (expectedSize != imageSize) {
/* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...]
return GL_FALSE;
error:
+ /* Note: not all error paths exit through here. */
_mesa_error(ctx, error, "glCompressedTexImage%dD(%s)", dimensions, reason);
return GL_TRUE;
}
/**
* Test glTexSubImage[123]D() parameters for errors.
- *
+ *
* \param ctx GL context.
* \param dimensions texture image dimensions (must be 1, 2 or 3).
* \param target texture target given by the user (already validated)
* \param width image width given by the user.
* \param height image height given by the user.
* \param depth image depth given by the user.
- *
+ *
* \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
*
* Verifies each of the parameters against the constants specified in
/**
* Test glCopyTexImage[12]D() parameters for errors.
- *
+ *
* \param ctx GL context.
* \param dimensions texture image dimensions (must be 1, 2 or 3).
* \param target texture target given by the user.
* \param width image width given by the user.
* \param height image height given by the user.
* \param border texture border.
- *
+ *
* \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
- *
+ *
* Verifies each of the parameters against the constants specified in
* __struct gl_contextRec::Const and the supported extensions, and according
* to the OpenGL specification.
_mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)",
dimensions, _mesa_lookup_enum_by_nr(target));
return GL_TRUE;
- }
+ }
/* level check */
if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
break;
default:
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage%dD(internalFormat)", dimensions);
+ "glCopyTexImage%dD(internalFormat=%s)", dimensions,
+ _mesa_lookup_enum_by_nr(internalFormat));
return GL_TRUE;
}
}
baseFormat = _mesa_base_tex_format(ctx, internalFormat);
if (baseFormat < 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexImage%dD(internalFormat)", dimensions);
+ "glCopyTexImage%dD(internalFormat=%s)", dimensions,
+ _mesa_lookup_enum_by_nr(internalFormat));
return GL_TRUE;
}
if (_mesa_is_color_format(internalFormat)) {
if (rb_base_format < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage%dD(internalFormat)", dimensions);
+ "glCopyTexImage%dD(internalFormat=%s)", dimensions,
+ _mesa_lookup_enum_by_nr(internalFormat));
return GL_TRUE;
}
}
}
if (!valid) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexImage%dD(internalFormat)", dimensions);
+ "glCopyTexImage%dD(internalFormat=%s)", dimensions,
+ _mesa_lookup_enum_by_nr(internalFormat));
return GL_TRUE;
}
}
}
}
- if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
- _mesa_is_cube_face(target)) && width != height) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage2D(cube width != height)");
- return GL_TRUE;
- }
-
if (_mesa_is_compressed_format(ctx, internalFormat)) {
if (!target_can_be_compressed(ctx, target, internalFormat)) {
_mesa_error(ctx, GL_INVALID_ENUM,
att->Texture == texObj &&
att->TextureLevel == level &&
att->CubeMapFace == face) {
- ASSERT(_mesa_get_attachment_teximage(att));
- /* Tell driver about the new renderbuffer texture */
- ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
+ _mesa_update_texture_renderbuffer(ctx, ctx->DrawBuffer, att);
+ ASSERT(att->Renderbuffer->TexImage);
/* Mark fb status as indeterminate to force re-validation */
fb->_Status = 0;
}
* for efficient texture memory layout/allocation. In particular, this
* comes up during automatic mipmap generation.
*/
-gl_format
+mesa_format
_mesa_choose_texture_format(struct gl_context *ctx,
struct gl_texture_object *texObj,
GLenum target, GLint level,
GLenum internalFormat, GLenum format, GLenum type)
{
- gl_format f;
+ mesa_format f;
/* see if we've already chosen a format for the previous level */
if (level > 0) {
}
/* If the application requested compression to an S3TC format but we don't
- * have the DTXn library, force a generic compressed format instead.
+ * have the DXTn library, force a generic compressed format instead.
*/
if (internalFormat != format && format != GL_NONE) {
const GLenum before = internalFormat;
return f;
}
+
/**
* Adjust pixel unpack params and image dimensions to strip off the
* one-pixel texture border.
*height = *height - 2; /* reduce the height by two border pixels */
}
- if (*depth >= 3 && target != GL_TEXTURE_2D_ARRAY && target != GL_TEXTURE_CUBE_MAP_ARRAY) {
+ if (*depth >= 3 &&
+ target != GL_TEXTURE_2D_ARRAY &&
+ target != GL_TEXTURE_CUBE_MAP_ARRAY) {
unpackNew->SkipImages++; /* skip the border */
*depth = *depth - 2; /* reduce the depth by two border pixels */
}
struct gl_pixelstore_attrib unpack_no_border;
const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
struct gl_texture_object *texObj;
- gl_format texFormat;
+ mesa_format texFormat;
GLboolean dimensionsOK, sizeOK;
FLUSH_VERTICES(ctx, 0);
height, depth, border);
/* check that the texture won't take too much memory, etc */
- sizeOK = ctx->Driver.TestProxyTexImage(ctx, _mesa_get_proxy_target(target),
+ sizeOK = ctx->Driver.TestProxyTexImage(ctx, proxy_target(target),
level, texFormat,
width, height, depth, border);
_mesa_update_fbo_texture(ctx, texObj, face, level);
- _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+ _mesa_dirty_texobj(ctx, texObj);
}
}
_mesa_unlock_texture(ctx, texObj);
valid_target = ctx->Extensions.OES_EGL_image;
break;
case GL_TEXTURE_EXTERNAL_OES:
- valid_target = ctx->Extensions.OES_EGL_image_external;
+ valid_target =
+ _mesa_is_gles(ctx) ? ctx->Extensions.OES_EGL_image_external : false;
break;
default:
valid_target = false;
ctx->Driver.EGLImageTargetTexture2D(ctx, target,
texObj, texImage, image);
- _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+ _mesa_dirty_texobj(ctx, texObj);
}
_mesa_unlock_texture(ctx, texObj);
_mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)",
dims, _mesa_lookup_enum_by_nr(target));
return;
- }
+ }
if (ctx->NewState & _NEW_PIXEL)
_mesa_update_state(ctx);
check_gen_mipmap(ctx, target, texObj, level);
- ctx->NewState |= _NEW_TEXTURE;
+ /* NOTE: Don't signal _NEW_TEXTURE since we've only changed
+ * the texel data, not the texture format, size, etc.
+ */
}
}
_mesa_unlock_texture(ctx, texObj);
* from. This depends on whether the texture contains color or depth values.
*/
static struct gl_renderbuffer *
-get_copy_tex_image_source(struct gl_context *ctx, gl_format texFormat)
+get_copy_tex_image_source(struct gl_context *ctx, mesa_format texFormat)
{
if (_mesa_get_format_bits(texFormat, GL_DEPTH_BITS) > 0) {
/* reading from depth/stencil buffer */
}
}
+static void
+copytexsubimage_by_slice(struct gl_context *ctx,
+ struct gl_texture_image *texImage,
+ GLuint dims,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ struct gl_renderbuffer *rb,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+ int slice;
+
+ /* For 1D arrays, we copy each scanline of the source rectangle into the
+ * next array slice.
+ */
+ assert(zoffset == 0);
+
+ for (slice = 0; slice < height; slice++) {
+ assert(yoffset + slice < texImage->Height);
+ ctx->Driver.CopyTexSubImage(ctx, 2, texImage,
+ xoffset, 0, yoffset + slice,
+ rb, x, y + slice, width, 1);
+ }
+ } else {
+ ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
+ xoffset, yoffset, zoffset,
+ rb, x, y, width, height);
+ }
+}
/**
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
const GLuint face = _mesa_tex_target_to_face(target);
- gl_format texFormat;
+ mesa_format texFormat;
FLUSH_VERTICES(ctx, 0);
internalFormat, GL_NONE, GL_NONE);
assert(texFormat != MESA_FORMAT_NONE);
- if (!ctx->Driver.TestProxyTexImage(ctx, _mesa_get_proxy_target(target),
+ if (!ctx->Driver.TestProxyTexImage(ctx, proxy_target(target),
level, texFormat,
width, height, 1, border)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY,
struct gl_renderbuffer *srcRb =
get_copy_tex_image_source(ctx, texImage->TexFormat);
- ctx->Driver.CopyTexSubImage(ctx, dims, texImage, dstX, dstY, dstZ,
- srcRb, srcX, srcY, width, height);
+ copytexsubimage_by_slice(ctx, texImage, dims,
+ dstX, dstY, dstZ,
+ srcRb, srcX, srcY, width, height);
}
check_gen_mipmap(ctx, target, texObj, level);
_mesa_update_fbo_texture(ctx, texObj, face, level);
- _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+ _mesa_dirty_texobj(ctx, texObj);
}
}
_mesa_unlock_texture(ctx, texObj);
struct gl_renderbuffer *srcRb =
get_copy_tex_image_source(ctx, texImage->TexFormat);
- ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
- xoffset, yoffset, zoffset,
- srcRb, x, y, width, height);
+ copytexsubimage_by_slice(ctx, texImage, dims,
+ xoffset, yoffset, zoffset,
+ srcRb, x, y, width, height);
check_gen_mipmap(ctx, target, texObj, level);
- ctx->NewState |= _NEW_TEXTURE;
+ /* NOTE: Don't signal _NEW_TEXTURE since we've only changed
+ * the texel data, not the texture format, size, etc.
+ */
}
}
_mesa_unlock_texture(ctx, texObj);
targetOK = GL_FALSE;
break;
}
-
+
if (!targetOK) {
_mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target)",
dims);
check_gen_mipmap(ctx, target, texObj, level);
- ctx->NewState |= _NEW_TEXTURE;
+ /* NOTE: Don't signal _NEW_TEXTURE since we've only changed
+ * the texel data, not the texture format, size, etc.
+ */
}
}
_mesa_unlock_texture(ctx, texObj);
width, height, depth, format, imageSize, data);
}
-static gl_format
+static mesa_format
get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
{
+ if (ctx->API != API_OPENGL_CORE) {
+ switch (internalFormat) {
+ case GL_ALPHA8:
+ return MESA_FORMAT_A_UNORM8;
+ case GL_ALPHA16:
+ return MESA_FORMAT_A_UNORM16;
+ case GL_ALPHA16F_ARB:
+ return MESA_FORMAT_A_FLOAT16;
+ case GL_ALPHA32F_ARB:
+ return MESA_FORMAT_A_FLOAT32;
+ case GL_ALPHA8I_EXT:
+ return MESA_FORMAT_A_SINT8;
+ case GL_ALPHA16I_EXT:
+ return MESA_FORMAT_A_SINT16;
+ case GL_ALPHA32I_EXT:
+ return MESA_FORMAT_A_SINT32;
+ case GL_ALPHA8UI_EXT:
+ return MESA_FORMAT_A_UINT8;
+ case GL_ALPHA16UI_EXT:
+ return MESA_FORMAT_A_UINT16;
+ case GL_ALPHA32UI_EXT:
+ return MESA_FORMAT_A_UINT32;
+ case GL_LUMINANCE8:
+ return MESA_FORMAT_L_UNORM8;
+ case GL_LUMINANCE16:
+ return MESA_FORMAT_L_UNORM16;
+ case GL_LUMINANCE16F_ARB:
+ return MESA_FORMAT_L_FLOAT16;
+ case GL_LUMINANCE32F_ARB:
+ return MESA_FORMAT_L_FLOAT32;
+ case GL_LUMINANCE8I_EXT:
+ return MESA_FORMAT_L_SINT8;
+ case GL_LUMINANCE16I_EXT:
+ return MESA_FORMAT_L_SINT16;
+ case GL_LUMINANCE32I_EXT:
+ return MESA_FORMAT_L_SINT32;
+ case GL_LUMINANCE8UI_EXT:
+ return MESA_FORMAT_L_UINT8;
+ case GL_LUMINANCE16UI_EXT:
+ return MESA_FORMAT_L_UINT16;
+ case GL_LUMINANCE32UI_EXT:
+ return MESA_FORMAT_L_UINT32;
+ case GL_LUMINANCE8_ALPHA8:
+ return MESA_FORMAT_L8A8_UNORM;
+ case GL_LUMINANCE16_ALPHA16:
+ return MESA_FORMAT_L16A16_UNORM;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ return MESA_FORMAT_LA_FLOAT16;
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ return MESA_FORMAT_LA_FLOAT32;
+ case GL_LUMINANCE_ALPHA8I_EXT:
+ return MESA_FORMAT_LA_SINT8;
+ case GL_LUMINANCE_ALPHA16I_EXT:
+ return MESA_FORMAT_LA_SINT8;
+ case GL_LUMINANCE_ALPHA32I_EXT:
+ return MESA_FORMAT_LA_SINT16;
+ case GL_LUMINANCE_ALPHA8UI_EXT:
+ return MESA_FORMAT_LA_UINT8;
+ case GL_LUMINANCE_ALPHA16UI_EXT:
+ return MESA_FORMAT_LA_UINT16;
+ case GL_LUMINANCE_ALPHA32UI_EXT:
+ return MESA_FORMAT_LA_UINT32;
+ case GL_INTENSITY8:
+ return MESA_FORMAT_I_UNORM8;
+ case GL_INTENSITY16:
+ return MESA_FORMAT_I_UNORM16;
+ case GL_INTENSITY16F_ARB:
+ return MESA_FORMAT_I_FLOAT16;
+ case GL_INTENSITY32F_ARB:
+ return MESA_FORMAT_I_FLOAT32;
+ case GL_INTENSITY8I_EXT:
+ return MESA_FORMAT_I_SINT8;
+ case GL_INTENSITY16I_EXT:
+ return MESA_FORMAT_I_SINT16;
+ case GL_INTENSITY32I_EXT:
+ return MESA_FORMAT_I_SINT32;
+ case GL_INTENSITY8UI_EXT:
+ return MESA_FORMAT_I_UINT8;
+ case GL_INTENSITY16UI_EXT:
+ return MESA_FORMAT_I_UINT16;
+ case GL_INTENSITY32UI_EXT:
+ return MESA_FORMAT_I_UINT32;
+ default:
+ break;
+ }
+ }
+
+ if (ctx->API == API_OPENGL_CORE &&
+ ctx->Extensions.ARB_texture_buffer_object_rgb32) {
+ switch (internalFormat) {
+ case GL_RGB32F:
+ return MESA_FORMAT_RGB_FLOAT32;
+ case GL_RGB32UI:
+ return MESA_FORMAT_RGB_UINT32;
+ case GL_RGB32I:
+ return MESA_FORMAT_RGB_SINT32;
+ default:
+ break;
+ }
+ }
+
switch (internalFormat) {
- case GL_ALPHA8:
- return MESA_FORMAT_A8;
- case GL_ALPHA16:
- return MESA_FORMAT_A16;
- case GL_ALPHA16F_ARB:
- return MESA_FORMAT_ALPHA_FLOAT16;
- case GL_ALPHA32F_ARB:
- return MESA_FORMAT_ALPHA_FLOAT32;
- case GL_ALPHA8I_EXT:
- return MESA_FORMAT_ALPHA_INT8;
- case GL_ALPHA16I_EXT:
- return MESA_FORMAT_ALPHA_INT16;
- case GL_ALPHA32I_EXT:
- return MESA_FORMAT_ALPHA_INT32;
- case GL_ALPHA8UI_EXT:
- return MESA_FORMAT_ALPHA_UINT8;
- case GL_ALPHA16UI_EXT:
- return MESA_FORMAT_ALPHA_UINT16;
- case GL_ALPHA32UI_EXT:
- return MESA_FORMAT_ALPHA_UINT32;
- case GL_LUMINANCE8:
- return MESA_FORMAT_L8;
- case GL_LUMINANCE16:
- return MESA_FORMAT_L16;
- case GL_LUMINANCE16F_ARB:
- return MESA_FORMAT_LUMINANCE_FLOAT16;
- case GL_LUMINANCE32F_ARB:
- return MESA_FORMAT_LUMINANCE_FLOAT32;
- case GL_LUMINANCE8I_EXT:
- return MESA_FORMAT_LUMINANCE_INT8;
- case GL_LUMINANCE16I_EXT:
- return MESA_FORMAT_LUMINANCE_INT16;
- case GL_LUMINANCE32I_EXT:
- return MESA_FORMAT_LUMINANCE_INT32;
- case GL_LUMINANCE8UI_EXT:
- return MESA_FORMAT_LUMINANCE_UINT8;
- case GL_LUMINANCE16UI_EXT:
- return MESA_FORMAT_LUMINANCE_UINT16;
- case GL_LUMINANCE32UI_EXT:
- return MESA_FORMAT_LUMINANCE_UINT32;
- case GL_LUMINANCE8_ALPHA8:
- return MESA_FORMAT_AL88;
- case GL_LUMINANCE16_ALPHA16:
- return MESA_FORMAT_AL1616;
- case GL_LUMINANCE_ALPHA16F_ARB:
- return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16;
- case GL_LUMINANCE_ALPHA32F_ARB:
- return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32;
- case GL_LUMINANCE_ALPHA8I_EXT:
- return MESA_FORMAT_LUMINANCE_ALPHA_INT8;
- case GL_LUMINANCE_ALPHA16I_EXT:
- return MESA_FORMAT_LUMINANCE_ALPHA_INT8;
- case GL_LUMINANCE_ALPHA32I_EXT:
- return MESA_FORMAT_LUMINANCE_ALPHA_INT16;
- case GL_LUMINANCE_ALPHA8UI_EXT:
- return MESA_FORMAT_LUMINANCE_ALPHA_UINT8;
- case GL_LUMINANCE_ALPHA16UI_EXT:
- return MESA_FORMAT_LUMINANCE_ALPHA_UINT16;
- case GL_LUMINANCE_ALPHA32UI_EXT:
- return MESA_FORMAT_LUMINANCE_ALPHA_UINT32;
- case GL_INTENSITY8:
- return MESA_FORMAT_I8;
- case GL_INTENSITY16:
- return MESA_FORMAT_I16;
- case GL_INTENSITY16F_ARB:
- return MESA_FORMAT_INTENSITY_FLOAT16;
- case GL_INTENSITY32F_ARB:
- return MESA_FORMAT_INTENSITY_FLOAT32;
- case GL_INTENSITY8I_EXT:
- return MESA_FORMAT_INTENSITY_INT8;
- case GL_INTENSITY16I_EXT:
- return MESA_FORMAT_INTENSITY_INT16;
- case GL_INTENSITY32I_EXT:
- return MESA_FORMAT_INTENSITY_INT32;
- case GL_INTENSITY8UI_EXT:
- return MESA_FORMAT_INTENSITY_UINT8;
- case GL_INTENSITY16UI_EXT:
- return MESA_FORMAT_INTENSITY_UINT16;
- case GL_INTENSITY32UI_EXT:
- return MESA_FORMAT_INTENSITY_UINT32;
case GL_RGBA8:
- return MESA_FORMAT_RGBA8888_REV;
+ return MESA_FORMAT_R8G8B8A8_UNORM;
case GL_RGBA16:
- return MESA_FORMAT_RGBA_16;
+ return MESA_FORMAT_RGBA_UNORM16;
case GL_RGBA16F_ARB:
return MESA_FORMAT_RGBA_FLOAT16;
case GL_RGBA32F_ARB:
return MESA_FORMAT_RGBA_FLOAT32;
case GL_RGBA8I_EXT:
- return MESA_FORMAT_RGBA_INT8;
+ return MESA_FORMAT_RGBA_SINT8;
case GL_RGBA16I_EXT:
- return MESA_FORMAT_RGBA_INT16;
+ return MESA_FORMAT_RGBA_SINT16;
case GL_RGBA32I_EXT:
- return MESA_FORMAT_RGBA_INT32;
+ return MESA_FORMAT_RGBA_SINT32;
case GL_RGBA8UI_EXT:
return MESA_FORMAT_RGBA_UINT8;
case GL_RGBA16UI_EXT:
return MESA_FORMAT_RGBA_UINT32;
case GL_RG8:
- return MESA_FORMAT_GR88;
+ return MESA_FORMAT_R8G8_UNORM;
case GL_RG16:
- return MESA_FORMAT_GR1616;
+ return MESA_FORMAT_R16G16_UNORM;
case GL_RG16F:
return MESA_FORMAT_RG_FLOAT16;
case GL_RG32F:
return MESA_FORMAT_RG_FLOAT32;
case GL_RG8I:
- return MESA_FORMAT_RG_INT8;
+ return MESA_FORMAT_RG_SINT8;
case GL_RG16I:
- return MESA_FORMAT_RG_INT16;
+ return MESA_FORMAT_RG_SINT16;
case GL_RG32I:
- return MESA_FORMAT_RG_INT32;
+ return MESA_FORMAT_RG_SINT32;
case GL_RG8UI:
return MESA_FORMAT_RG_UINT8;
case GL_RG16UI:
return MESA_FORMAT_RG_UINT32;
case GL_R8:
- return MESA_FORMAT_R8;
+ return MESA_FORMAT_R_UNORM8;
case GL_R16:
- return MESA_FORMAT_R16;
+ return MESA_FORMAT_R_UNORM16;
case GL_R16F:
return MESA_FORMAT_R_FLOAT16;
case GL_R32F:
return MESA_FORMAT_R_FLOAT32;
case GL_R8I:
- return MESA_FORMAT_R_INT8;
+ return MESA_FORMAT_R_SINT8;
case GL_R16I:
- return MESA_FORMAT_R_INT16;
+ return MESA_FORMAT_R_SINT16;
case GL_R32I:
- return MESA_FORMAT_R_INT32;
+ return MESA_FORMAT_R_SINT32;
case GL_R8UI:
return MESA_FORMAT_R_UINT8;
case GL_R16UI:
case GL_R32UI:
return MESA_FORMAT_R_UINT32;
- case GL_RGB32F:
- return MESA_FORMAT_RGB_FLOAT32;
- case GL_RGB32UI:
- return MESA_FORMAT_RGB_UINT32;
- case GL_RGB32I:
- return MESA_FORMAT_RGB_INT32;
-
default:
return MESA_FORMAT_NONE;
}
}
-static gl_format
-validate_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
+
+mesa_format
+_mesa_validate_texbuffer_format(const struct gl_context *ctx,
+ GLenum internalFormat)
{
- gl_format format = get_texbuffer_format(ctx, internalFormat);
+ mesa_format format = get_texbuffer_format(ctx, internalFormat);
GLenum datatype;
if (format == MESA_FORMAT_NONE)
return MESA_FORMAT_NONE;
datatype = _mesa_get_format_datatype(format);
- if (datatype == GL_FLOAT && !ctx->Extensions.ARB_texture_float)
- return MESA_FORMAT_NONE;
- if (datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel)
+ /* The GL_ARB_texture_buffer_object spec says:
+ *
+ * "If ARB_texture_float is not supported, references to the
+ * floating-point internal formats provided by that extension should be
+ * removed, and such formats may not be passed to TexBufferARB."
+ *
+ * As a result, GL_HALF_FLOAT internal format depends on both
+ * GL_ARB_texture_float and GL_ARB_half_float_pixel.
+ */
+ if ((datatype == GL_FLOAT || datatype == GL_HALF_FLOAT) &&
+ !ctx->Extensions.ARB_texture_float)
return MESA_FORMAT_NONE;
- /* The GL_ARB_texture_rg and GL_ARB_texture_buffer_object specs don't make
- * any mention of R/RG formats, but they appear in the GL 3.1 core
- * specification.
- */
- if (ctx->Version <= 30) {
+ if (!ctx->Extensions.ARB_texture_rg) {
GLenum base_format = _mesa_get_format_base_format(format);
-
if (base_format == GL_R || base_format == GL_RG)
- return MESA_FORMAT_NONE;
+ return MESA_FORMAT_NONE;
}
if (!ctx->Extensions.ARB_texture_buffer_object_rgb32) {
GLintptr offset, GLsizeiptr size)
{
struct gl_texture_object *texObj;
- gl_format format;
+ mesa_format format;
FLUSH_VERTICES(ctx, 0);
return;
}
- format = validate_texbuffer_format(ctx, internalFormat);
+ format = _mesa_validate_texbuffer_format(ctx, internalFormat);
if (format == MESA_FORMAT_NONE) {
_mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(internalFormat 0x%x)",
internalFormat);
_mesa_unlock_texture(ctx, texObj);
}
+
/** GL_ARB_texture_buffer_object */
void GLAPIENTRY
_mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
texbufferrange(ctx, target, internalFormat, bufObj, 0, buffer ? -1 : 0);
}
+
/** GL_ARB_texture_buffer_range */
void GLAPIENTRY
_mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
texbufferrange(ctx, target, internalFormat, bufObj, offset, size);
}
+
static GLboolean
is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
{
return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX;
}
+
/** GL_ARB_texture_multisample */
static GLboolean
check_multisample_target(GLuint dims, GLenum target)
}
}
+
static void
teximagemultisample(GLuint dims, GLenum target, GLsizei samples,
GLint internalformat, GLsizei width, GLsizei height,
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
GLboolean sizeOK, dimensionsOK;
- gl_format texFormat;
+ mesa_format texFormat;
GLenum sample_count_error;
GET_CURRENT_CONTEXT(ctx);
if (_mesa_is_proxy_texture(target)) {
if (dimensionsOK && sizeOK) {
- _mesa_init_teximage_fields(ctx, texImage,
- width, height, depth, 0, internalformat, texFormat);
- texImage->NumSamples = samples;
- texImage->FixedSampleLocations = fixedsamplelocations;
+ init_teximage_fields_ms(ctx, texImage, width, height, depth, 0,
+ internalformat, texFormat,
+ samples, fixedsamplelocations);
}
else {
/* clear all image fields */
- _mesa_init_teximage_fields(ctx, texImage,
- 0, 0, 0, 0, GL_NONE, MESA_FORMAT_NONE);
+ clear_teximage_fields(texImage);
}
}
else {
ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
- _mesa_init_teximage_fields(ctx, texImage,
- width, height, depth, 0, internalformat, texFormat);
-
- texImage->NumSamples = samples;
- texImage->FixedSampleLocations = fixedsamplelocations;
+ init_teximage_fields_ms(ctx, texImage, width, height, depth, 0,
+ internalformat, texFormat,
+ samples, fixedsamplelocations);
if (width > 0 && height > 0 && depth > 0) {
-
if (!ctx->Driver.AllocTextureStorage(ctx, texObj, 1,
width, height, depth)) {
/* tidy up the texture image state. strictly speaking,
}
texObj->Immutable = immutable;
+
+ if (immutable) {
+ _mesa_set_texture_view_state(ctx, texObj, target, 1);
+ }
+
_mesa_update_fbo_texture(ctx, texObj, 0, 0);
}
}
+
void GLAPIENTRY
_mesa_TexImage2DMultisample(GLenum target, GLsizei samples,
- GLint internalformat, GLsizei width,
+ GLenum internalformat, GLsizei width,
GLsizei height, GLboolean fixedsamplelocations)
{
teximagemultisample(2, target, samples, internalformat,
- width, height, 1, fixedsamplelocations, GL_FALSE, "glTexImage2DMultisample");
+ width, height, 1, fixedsamplelocations, GL_FALSE,
+ "glTexImage2DMultisample");
}
+
void GLAPIENTRY
_mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
- GLint internalformat, GLsizei width,
+ GLenum internalformat, GLsizei width,
GLsizei height, GLsizei depth,
GLboolean fixedsamplelocations)
{
teximagemultisample(3, target, samples, internalformat,
- width, height, depth, fixedsamplelocations, GL_FALSE, "glTexImage3DMultisample");
+ width, height, depth, fixedsamplelocations, GL_FALSE,
+ "glTexImage3DMultisample");
}
GLsizei height, GLboolean fixedsamplelocations)
{
teximagemultisample(2, target, samples, internalformat,
- width, height, 1, fixedsamplelocations, GL_TRUE, "glTexStorage2DMultisample");
+ width, height, 1, fixedsamplelocations, GL_TRUE,
+ "glTexStorage2DMultisample");
}
+
void GLAPIENTRY
_mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width,
GLboolean fixedsamplelocations)
{
teximagemultisample(3, target, samples, internalformat,
- width, height, depth, fixedsamplelocations, GL_TRUE, "glTexStorage3DMultisample");
+ width, height, depth, fixedsamplelocations, GL_TRUE,
+ "glTexStorage3DMultisample");
}