1af69d88dSmrg/* 2af69d88dSmrg * Copyright 2013 Intel Corporation 3af69d88dSmrg * 4af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5af69d88dSmrg * copy of this software and associated documentation files (the "Software"), 6af69d88dSmrg * to deal in the Software without restriction, including without limitation 7af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9af69d88dSmrg * Software is furnished to do so, subject to the following conditions: 10af69d88dSmrg * 11af69d88dSmrg * The above copyright notice and this permission notice (including the next 12af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the 13af69d88dSmrg * Software. 14af69d88dSmrg * 15af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19af69d88dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20af69d88dSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21af69d88dSmrg * DEALINGS IN THE SOFTWARE. 22af69d88dSmrg * 23af69d88dSmrg * Authors: 24af69d88dSmrg * Francisco Jerez <currojerez@riseup.net> 25af69d88dSmrg */ 26af69d88dSmrg 27af69d88dSmrg#include <assert.h> 28af69d88dSmrg 29af69d88dSmrg#include "shaderimage.h" 30af69d88dSmrg#include "mtypes.h" 31af69d88dSmrg#include "formats.h" 32af69d88dSmrg#include "errors.h" 3301e04c3fSmrg#include "hash.h" 34af69d88dSmrg#include "context.h" 35af69d88dSmrg#include "texobj.h" 36af69d88dSmrg#include "teximage.h" 37af69d88dSmrg#include "enums.h" 38af69d88dSmrg 3901e04c3fSmrgmesa_format 4001e04c3fSmrg_mesa_get_shader_image_format(GLenum format) 41af69d88dSmrg{ 42af69d88dSmrg switch (format) { 43af69d88dSmrg case GL_RGBA32F: 44af69d88dSmrg return MESA_FORMAT_RGBA_FLOAT32; 45af69d88dSmrg 46af69d88dSmrg case GL_RGBA16F: 47af69d88dSmrg return MESA_FORMAT_RGBA_FLOAT16; 48af69d88dSmrg 49af69d88dSmrg case GL_RG32F: 50af69d88dSmrg return MESA_FORMAT_RG_FLOAT32; 51af69d88dSmrg 52af69d88dSmrg case GL_RG16F: 53af69d88dSmrg return MESA_FORMAT_RG_FLOAT16; 54af69d88dSmrg 55af69d88dSmrg case GL_R11F_G11F_B10F: 56af69d88dSmrg return MESA_FORMAT_R11G11B10_FLOAT; 57af69d88dSmrg 58af69d88dSmrg case GL_R32F: 59af69d88dSmrg return MESA_FORMAT_R_FLOAT32; 60af69d88dSmrg 61af69d88dSmrg case GL_R16F: 62af69d88dSmrg return MESA_FORMAT_R_FLOAT16; 63af69d88dSmrg 64af69d88dSmrg case GL_RGBA32UI: 65af69d88dSmrg return MESA_FORMAT_RGBA_UINT32; 66af69d88dSmrg 67af69d88dSmrg case GL_RGBA16UI: 68af69d88dSmrg return MESA_FORMAT_RGBA_UINT16; 69af69d88dSmrg 70af69d88dSmrg case GL_RGB10_A2UI: 71af69d88dSmrg return MESA_FORMAT_R10G10B10A2_UINT; 72af69d88dSmrg 73af69d88dSmrg case GL_RGBA8UI: 74af69d88dSmrg return MESA_FORMAT_RGBA_UINT8; 75af69d88dSmrg 76af69d88dSmrg case GL_RG32UI: 77af69d88dSmrg return MESA_FORMAT_RG_UINT32; 78af69d88dSmrg 79af69d88dSmrg case GL_RG16UI: 80af69d88dSmrg return MESA_FORMAT_RG_UINT16; 81af69d88dSmrg 82af69d88dSmrg case GL_RG8UI: 83af69d88dSmrg return MESA_FORMAT_RG_UINT8; 84af69d88dSmrg 85af69d88dSmrg case GL_R32UI: 86af69d88dSmrg return MESA_FORMAT_R_UINT32; 87af69d88dSmrg 88af69d88dSmrg case GL_R16UI: 89af69d88dSmrg return MESA_FORMAT_R_UINT16; 90af69d88dSmrg 91af69d88dSmrg case GL_R8UI: 92af69d88dSmrg return MESA_FORMAT_R_UINT8; 93af69d88dSmrg 94af69d88dSmrg case GL_RGBA32I: 95af69d88dSmrg return MESA_FORMAT_RGBA_SINT32; 96af69d88dSmrg 97af69d88dSmrg case GL_RGBA16I: 98af69d88dSmrg return MESA_FORMAT_RGBA_SINT16; 99af69d88dSmrg 100af69d88dSmrg case GL_RGBA8I: 101af69d88dSmrg return MESA_FORMAT_RGBA_SINT8; 102af69d88dSmrg 103af69d88dSmrg case GL_RG32I: 104af69d88dSmrg return MESA_FORMAT_RG_SINT32; 105af69d88dSmrg 106af69d88dSmrg case GL_RG16I: 107af69d88dSmrg return MESA_FORMAT_RG_SINT16; 108af69d88dSmrg 109af69d88dSmrg case GL_RG8I: 110af69d88dSmrg return MESA_FORMAT_RG_SINT8; 111af69d88dSmrg 112af69d88dSmrg case GL_R32I: 113af69d88dSmrg return MESA_FORMAT_R_SINT32; 114af69d88dSmrg 115af69d88dSmrg case GL_R16I: 116af69d88dSmrg return MESA_FORMAT_R_SINT16; 117af69d88dSmrg 118af69d88dSmrg case GL_R8I: 119af69d88dSmrg return MESA_FORMAT_R_SINT8; 120af69d88dSmrg 121af69d88dSmrg case GL_RGBA16: 122af69d88dSmrg return MESA_FORMAT_RGBA_UNORM16; 123af69d88dSmrg 124af69d88dSmrg case GL_RGB10_A2: 125af69d88dSmrg return MESA_FORMAT_R10G10B10A2_UNORM; 126af69d88dSmrg 127af69d88dSmrg case GL_RGBA8: 1287ec681f3Smrg return MESA_FORMAT_RGBA_UNORM8; 129af69d88dSmrg 130af69d88dSmrg case GL_RG16: 1317ec681f3Smrg return MESA_FORMAT_RG_UNORM16; 132af69d88dSmrg 133af69d88dSmrg case GL_RG8: 1347ec681f3Smrg return MESA_FORMAT_RG_UNORM8; 135af69d88dSmrg 136af69d88dSmrg case GL_R16: 137af69d88dSmrg return MESA_FORMAT_R_UNORM16; 138af69d88dSmrg 139af69d88dSmrg case GL_R8: 140af69d88dSmrg return MESA_FORMAT_R_UNORM8; 141af69d88dSmrg 142af69d88dSmrg case GL_RGBA16_SNORM: 143af69d88dSmrg return MESA_FORMAT_RGBA_SNORM16; 144af69d88dSmrg 145af69d88dSmrg case GL_RGBA8_SNORM: 1467ec681f3Smrg return MESA_FORMAT_RGBA_SNORM8; 147af69d88dSmrg 148af69d88dSmrg case GL_RG16_SNORM: 1497ec681f3Smrg return MESA_FORMAT_RG_SNORM16; 150af69d88dSmrg 151af69d88dSmrg case GL_RG8_SNORM: 1527ec681f3Smrg return MESA_FORMAT_RG_SNORM8; 153af69d88dSmrg 154af69d88dSmrg case GL_R16_SNORM: 155af69d88dSmrg return MESA_FORMAT_R_SNORM16; 156af69d88dSmrg 157af69d88dSmrg case GL_R8_SNORM: 158af69d88dSmrg return MESA_FORMAT_R_SNORM8; 159af69d88dSmrg 160af69d88dSmrg default: 161af69d88dSmrg return MESA_FORMAT_NONE; 162af69d88dSmrg } 163af69d88dSmrg} 164af69d88dSmrg 165af69d88dSmrgenum image_format_class 166af69d88dSmrg{ 167af69d88dSmrg /** Not a valid image format. */ 168af69d88dSmrg IMAGE_FORMAT_CLASS_NONE = 0, 169af69d88dSmrg 170af69d88dSmrg /** Classes of image formats you can cast into each other. */ 171af69d88dSmrg /** \{ */ 172af69d88dSmrg IMAGE_FORMAT_CLASS_1X8, 173af69d88dSmrg IMAGE_FORMAT_CLASS_1X16, 174af69d88dSmrg IMAGE_FORMAT_CLASS_1X32, 175af69d88dSmrg IMAGE_FORMAT_CLASS_2X8, 176af69d88dSmrg IMAGE_FORMAT_CLASS_2X16, 177af69d88dSmrg IMAGE_FORMAT_CLASS_2X32, 178af69d88dSmrg IMAGE_FORMAT_CLASS_10_11_11, 179af69d88dSmrg IMAGE_FORMAT_CLASS_4X8, 180af69d88dSmrg IMAGE_FORMAT_CLASS_4X16, 181af69d88dSmrg IMAGE_FORMAT_CLASS_4X32, 182af69d88dSmrg IMAGE_FORMAT_CLASS_2_10_10_10 183af69d88dSmrg /** \} */ 184af69d88dSmrg}; 185af69d88dSmrg 186af69d88dSmrgstatic enum image_format_class 187af69d88dSmrgget_image_format_class(mesa_format format) 188af69d88dSmrg{ 189af69d88dSmrg switch (format) { 190af69d88dSmrg case MESA_FORMAT_RGBA_FLOAT32: 191af69d88dSmrg return IMAGE_FORMAT_CLASS_4X32; 192af69d88dSmrg 193af69d88dSmrg case MESA_FORMAT_RGBA_FLOAT16: 194af69d88dSmrg return IMAGE_FORMAT_CLASS_4X16; 195af69d88dSmrg 196af69d88dSmrg case MESA_FORMAT_RG_FLOAT32: 197af69d88dSmrg return IMAGE_FORMAT_CLASS_2X32; 198af69d88dSmrg 199af69d88dSmrg case MESA_FORMAT_RG_FLOAT16: 200af69d88dSmrg return IMAGE_FORMAT_CLASS_2X16; 201af69d88dSmrg 202af69d88dSmrg case MESA_FORMAT_R11G11B10_FLOAT: 203af69d88dSmrg return IMAGE_FORMAT_CLASS_10_11_11; 204af69d88dSmrg 205af69d88dSmrg case MESA_FORMAT_R_FLOAT32: 206af69d88dSmrg return IMAGE_FORMAT_CLASS_1X32; 207af69d88dSmrg 208af69d88dSmrg case MESA_FORMAT_R_FLOAT16: 209af69d88dSmrg return IMAGE_FORMAT_CLASS_1X16; 210af69d88dSmrg 211af69d88dSmrg case MESA_FORMAT_RGBA_UINT32: 212af69d88dSmrg return IMAGE_FORMAT_CLASS_4X32; 213af69d88dSmrg 214af69d88dSmrg case MESA_FORMAT_RGBA_UINT16: 215af69d88dSmrg return IMAGE_FORMAT_CLASS_4X16; 216af69d88dSmrg 217af69d88dSmrg case MESA_FORMAT_R10G10B10A2_UINT: 218af69d88dSmrg return IMAGE_FORMAT_CLASS_2_10_10_10; 219af69d88dSmrg 220af69d88dSmrg case MESA_FORMAT_RGBA_UINT8: 221af69d88dSmrg return IMAGE_FORMAT_CLASS_4X8; 222af69d88dSmrg 223af69d88dSmrg case MESA_FORMAT_RG_UINT32: 224af69d88dSmrg return IMAGE_FORMAT_CLASS_2X32; 225af69d88dSmrg 226af69d88dSmrg case MESA_FORMAT_RG_UINT16: 227af69d88dSmrg return IMAGE_FORMAT_CLASS_2X16; 228af69d88dSmrg 229af69d88dSmrg case MESA_FORMAT_RG_UINT8: 230af69d88dSmrg return IMAGE_FORMAT_CLASS_2X8; 231af69d88dSmrg 232af69d88dSmrg case MESA_FORMAT_R_UINT32: 233af69d88dSmrg return IMAGE_FORMAT_CLASS_1X32; 234af69d88dSmrg 235af69d88dSmrg case MESA_FORMAT_R_UINT16: 236af69d88dSmrg return IMAGE_FORMAT_CLASS_1X16; 237af69d88dSmrg 238af69d88dSmrg case MESA_FORMAT_R_UINT8: 239af69d88dSmrg return IMAGE_FORMAT_CLASS_1X8; 240af69d88dSmrg 241af69d88dSmrg case MESA_FORMAT_RGBA_SINT32: 242af69d88dSmrg return IMAGE_FORMAT_CLASS_4X32; 243af69d88dSmrg 244af69d88dSmrg case MESA_FORMAT_RGBA_SINT16: 245af69d88dSmrg return IMAGE_FORMAT_CLASS_4X16; 246af69d88dSmrg 247af69d88dSmrg case MESA_FORMAT_RGBA_SINT8: 248af69d88dSmrg return IMAGE_FORMAT_CLASS_4X8; 249af69d88dSmrg 250af69d88dSmrg case MESA_FORMAT_RG_SINT32: 251af69d88dSmrg return IMAGE_FORMAT_CLASS_2X32; 252af69d88dSmrg 253af69d88dSmrg case MESA_FORMAT_RG_SINT16: 254af69d88dSmrg return IMAGE_FORMAT_CLASS_2X16; 255af69d88dSmrg 256af69d88dSmrg case MESA_FORMAT_RG_SINT8: 257af69d88dSmrg return IMAGE_FORMAT_CLASS_2X8; 258af69d88dSmrg 259af69d88dSmrg case MESA_FORMAT_R_SINT32: 260af69d88dSmrg return IMAGE_FORMAT_CLASS_1X32; 261af69d88dSmrg 262af69d88dSmrg case MESA_FORMAT_R_SINT16: 263af69d88dSmrg return IMAGE_FORMAT_CLASS_1X16; 264af69d88dSmrg 265af69d88dSmrg case MESA_FORMAT_R_SINT8: 266af69d88dSmrg return IMAGE_FORMAT_CLASS_1X8; 267af69d88dSmrg 268af69d88dSmrg case MESA_FORMAT_RGBA_UNORM16: 269af69d88dSmrg return IMAGE_FORMAT_CLASS_4X16; 270af69d88dSmrg 271af69d88dSmrg case MESA_FORMAT_R10G10B10A2_UNORM: 272af69d88dSmrg return IMAGE_FORMAT_CLASS_2_10_10_10; 273af69d88dSmrg 2747ec681f3Smrg case MESA_FORMAT_RGBA_UNORM8: 275af69d88dSmrg return IMAGE_FORMAT_CLASS_4X8; 276af69d88dSmrg 2777ec681f3Smrg case MESA_FORMAT_RG_UNORM16: 278af69d88dSmrg return IMAGE_FORMAT_CLASS_2X16; 279af69d88dSmrg 2807ec681f3Smrg case MESA_FORMAT_RG_UNORM8: 281af69d88dSmrg return IMAGE_FORMAT_CLASS_2X8; 282af69d88dSmrg 283af69d88dSmrg case MESA_FORMAT_R_UNORM16: 284af69d88dSmrg return IMAGE_FORMAT_CLASS_1X16; 285af69d88dSmrg 286af69d88dSmrg case MESA_FORMAT_R_UNORM8: 287af69d88dSmrg return IMAGE_FORMAT_CLASS_1X8; 288af69d88dSmrg 289af69d88dSmrg case MESA_FORMAT_RGBA_SNORM16: 290af69d88dSmrg return IMAGE_FORMAT_CLASS_4X16; 291af69d88dSmrg 2927ec681f3Smrg case MESA_FORMAT_RGBA_SNORM8: 293af69d88dSmrg return IMAGE_FORMAT_CLASS_4X8; 294af69d88dSmrg 2957ec681f3Smrg case MESA_FORMAT_RG_SNORM16: 296af69d88dSmrg return IMAGE_FORMAT_CLASS_2X16; 297af69d88dSmrg 2987ec681f3Smrg case MESA_FORMAT_RG_SNORM8: 299af69d88dSmrg return IMAGE_FORMAT_CLASS_2X8; 300af69d88dSmrg 301af69d88dSmrg case MESA_FORMAT_R_SNORM16: 302af69d88dSmrg return IMAGE_FORMAT_CLASS_1X16; 303af69d88dSmrg 304af69d88dSmrg case MESA_FORMAT_R_SNORM8: 305af69d88dSmrg return IMAGE_FORMAT_CLASS_1X8; 306af69d88dSmrg 307af69d88dSmrg default: 308af69d88dSmrg return IMAGE_FORMAT_CLASS_NONE; 309af69d88dSmrg } 310af69d88dSmrg} 311af69d88dSmrg 31201e04c3fSmrgstatic GLenum 31301e04c3fSmrg_image_format_class_to_glenum(enum image_format_class class) 31401e04c3fSmrg{ 31501e04c3fSmrg switch (class) { 31601e04c3fSmrg case IMAGE_FORMAT_CLASS_NONE: 31701e04c3fSmrg return GL_NONE; 31801e04c3fSmrg case IMAGE_FORMAT_CLASS_1X8: 31901e04c3fSmrg return GL_IMAGE_CLASS_1_X_8; 32001e04c3fSmrg case IMAGE_FORMAT_CLASS_1X16: 32101e04c3fSmrg return GL_IMAGE_CLASS_1_X_16; 32201e04c3fSmrg case IMAGE_FORMAT_CLASS_1X32: 32301e04c3fSmrg return GL_IMAGE_CLASS_1_X_32; 32401e04c3fSmrg case IMAGE_FORMAT_CLASS_2X8: 32501e04c3fSmrg return GL_IMAGE_CLASS_2_X_8; 32601e04c3fSmrg case IMAGE_FORMAT_CLASS_2X16: 32701e04c3fSmrg return GL_IMAGE_CLASS_2_X_16; 32801e04c3fSmrg case IMAGE_FORMAT_CLASS_2X32: 32901e04c3fSmrg return GL_IMAGE_CLASS_2_X_32; 33001e04c3fSmrg case IMAGE_FORMAT_CLASS_10_11_11: 33101e04c3fSmrg return GL_IMAGE_CLASS_11_11_10; 33201e04c3fSmrg case IMAGE_FORMAT_CLASS_4X8: 33301e04c3fSmrg return GL_IMAGE_CLASS_4_X_8; 33401e04c3fSmrg case IMAGE_FORMAT_CLASS_4X16: 33501e04c3fSmrg return GL_IMAGE_CLASS_4_X_16; 33601e04c3fSmrg case IMAGE_FORMAT_CLASS_4X32: 33701e04c3fSmrg return GL_IMAGE_CLASS_4_X_32; 33801e04c3fSmrg case IMAGE_FORMAT_CLASS_2_10_10_10: 33901e04c3fSmrg return GL_IMAGE_CLASS_10_10_10_2; 34001e04c3fSmrg default: 34101e04c3fSmrg assert(!"Invalid image_format_class"); 34201e04c3fSmrg return GL_NONE; 34301e04c3fSmrg } 34401e04c3fSmrg} 34501e04c3fSmrg 34601e04c3fSmrgGLenum 34701e04c3fSmrg_mesa_get_image_format_class(GLenum format) 34801e04c3fSmrg{ 34901e04c3fSmrg mesa_format tex_format = _mesa_get_shader_image_format(format); 35001e04c3fSmrg if (tex_format == MESA_FORMAT_NONE) 35101e04c3fSmrg return GL_NONE; 35201e04c3fSmrg 35301e04c3fSmrg enum image_format_class class = get_image_format_class(tex_format); 35401e04c3fSmrg return _image_format_class_to_glenum(class); 35501e04c3fSmrg} 35601e04c3fSmrg 35701e04c3fSmrgbool 35801e04c3fSmrg_mesa_is_shader_image_format_supported(const struct gl_context *ctx, 35901e04c3fSmrg GLenum format) 36001e04c3fSmrg{ 36101e04c3fSmrg switch (format) { 36201e04c3fSmrg /* Formats supported on both desktop and ES GL, c.f. table 8.27 of the 36301e04c3fSmrg * OpenGL ES 3.1 specification. 36401e04c3fSmrg */ 36501e04c3fSmrg case GL_RGBA32F: 36601e04c3fSmrg case GL_RGBA16F: 36701e04c3fSmrg case GL_R32F: 36801e04c3fSmrg case GL_RGBA32UI: 36901e04c3fSmrg case GL_RGBA16UI: 37001e04c3fSmrg case GL_RGBA8UI: 37101e04c3fSmrg case GL_R32UI: 37201e04c3fSmrg case GL_RGBA32I: 37301e04c3fSmrg case GL_RGBA16I: 37401e04c3fSmrg case GL_RGBA8I: 37501e04c3fSmrg case GL_R32I: 37601e04c3fSmrg case GL_RGBA8: 37701e04c3fSmrg case GL_RGBA8_SNORM: 37801e04c3fSmrg return true; 37901e04c3fSmrg 38001e04c3fSmrg /* Formats supported on unextended desktop GL and the original 38101e04c3fSmrg * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2 38201e04c3fSmrg * specification or by GLES 3.1 with GL_NV_image_formats extension. 38301e04c3fSmrg */ 38401e04c3fSmrg case GL_RG32F: 38501e04c3fSmrg case GL_RG16F: 38601e04c3fSmrg case GL_R11F_G11F_B10F: 38701e04c3fSmrg case GL_R16F: 38801e04c3fSmrg case GL_RGB10_A2UI: 38901e04c3fSmrg case GL_RG32UI: 39001e04c3fSmrg case GL_RG16UI: 39101e04c3fSmrg case GL_RG8UI: 39201e04c3fSmrg case GL_R16UI: 39301e04c3fSmrg case GL_R8UI: 39401e04c3fSmrg case GL_RG32I: 39501e04c3fSmrg case GL_RG16I: 39601e04c3fSmrg case GL_RG8I: 39701e04c3fSmrg case GL_R16I: 39801e04c3fSmrg case GL_R8I: 39901e04c3fSmrg case GL_RGB10_A2: 40001e04c3fSmrg case GL_RG8: 40101e04c3fSmrg case GL_R8: 40201e04c3fSmrg case GL_RG8_SNORM: 40301e04c3fSmrg case GL_R8_SNORM: 40401e04c3fSmrg return true; 40501e04c3fSmrg 40601e04c3fSmrg /* Formats supported on unextended desktop GL and the original 40701e04c3fSmrg * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2 40801e04c3fSmrg * specification. 40901e04c3fSmrg * 41001e04c3fSmrg * Following formats are supported by GLES 3.1 with GL_NV_image_formats & 41101e04c3fSmrg * GL_EXT_texture_norm16 extensions. 41201e04c3fSmrg */ 41301e04c3fSmrg case GL_RGBA16: 41401e04c3fSmrg case GL_RGBA16_SNORM: 41501e04c3fSmrg case GL_RG16: 41601e04c3fSmrg case GL_RG16_SNORM: 41701e04c3fSmrg case GL_R16: 41801e04c3fSmrg case GL_R16_SNORM: 41901e04c3fSmrg return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx); 42001e04c3fSmrg 42101e04c3fSmrg default: 42201e04c3fSmrg return false; 42301e04c3fSmrg } 42401e04c3fSmrg} 42501e04c3fSmrg 42601e04c3fSmrgstruct gl_image_unit 42701e04c3fSmrg_mesa_default_image_unit(struct gl_context *ctx) 42801e04c3fSmrg{ 42901e04c3fSmrg const GLenum format = _mesa_is_desktop_gl(ctx) ? GL_R8 : GL_R32UI; 43001e04c3fSmrg const struct gl_image_unit u = { 43101e04c3fSmrg .Access = GL_READ_ONLY, 43201e04c3fSmrg .Format = format, 43301e04c3fSmrg ._ActualFormat = _mesa_get_shader_image_format(format) 43401e04c3fSmrg }; 43501e04c3fSmrg return u; 43601e04c3fSmrg} 43701e04c3fSmrg 43801e04c3fSmrgvoid 43901e04c3fSmrg_mesa_init_image_units(struct gl_context *ctx) 44001e04c3fSmrg{ 44101e04c3fSmrg unsigned i; 44201e04c3fSmrg 44301e04c3fSmrg ASSERT_BITFIELD_SIZE(struct gl_image_unit, Format, MESA_FORMAT_COUNT); 44401e04c3fSmrg 44501e04c3fSmrg for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) 44601e04c3fSmrg ctx->ImageUnits[i] = _mesa_default_image_unit(ctx); 44701e04c3fSmrg} 44801e04c3fSmrg 449b9abf16eSmaya 450b9abf16eSmayavoid 451b9abf16eSmaya_mesa_free_image_textures(struct gl_context *ctx) 452b9abf16eSmaya{ 453b9abf16eSmaya unsigned i; 454b9abf16eSmaya 455b9abf16eSmaya for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) 456b9abf16eSmaya _mesa_reference_texobj(&ctx->ImageUnits[i].TexObj, NULL); 457b9abf16eSmaya} 458b9abf16eSmaya 45901e04c3fSmrgGLboolean 46001e04c3fSmrg_mesa_is_image_unit_valid(struct gl_context *ctx, struct gl_image_unit *u) 461af69d88dSmrg{ 462af69d88dSmrg struct gl_texture_object *t = u->TexObj; 46301e04c3fSmrg mesa_format tex_format; 464af69d88dSmrg 46501e04c3fSmrg if (!t) 466af69d88dSmrg return GL_FALSE; 467af69d88dSmrg 46801e04c3fSmrg if (!t->_BaseComplete && !t->_MipmapComplete) 46901e04c3fSmrg _mesa_test_texobj_completeness(ctx, t); 470af69d88dSmrg 4717ec681f3Smrg if (u->Level < t->Attrib.BaseLevel || 47201e04c3fSmrg u->Level > t->_MaxLevel || 4737ec681f3Smrg (u->Level == t->Attrib.BaseLevel && !t->_BaseComplete) || 4747ec681f3Smrg (u->Level != t->Attrib.BaseLevel && !t->_MipmapComplete)) 475af69d88dSmrg return GL_FALSE; 476af69d88dSmrg 477af69d88dSmrg if (_mesa_tex_target_is_layered(t->Target) && 47801e04c3fSmrg u->_Layer >= _mesa_get_texture_layers(t, u->Level)) 479af69d88dSmrg return GL_FALSE; 480af69d88dSmrg 48101e04c3fSmrg if (t->Target == GL_TEXTURE_BUFFER) { 48201e04c3fSmrg tex_format = _mesa_get_shader_image_format(t->BufferObjectFormat); 48301e04c3fSmrg 48401e04c3fSmrg } else { 48501e04c3fSmrg struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ? 48601e04c3fSmrg t->Image[u->_Layer][u->Level] : 48701e04c3fSmrg t->Image[0][u->Level]); 48801e04c3fSmrg 48901e04c3fSmrg if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples) 49001e04c3fSmrg return GL_FALSE; 49101e04c3fSmrg 49201e04c3fSmrg tex_format = _mesa_get_shader_image_format(img->InternalFormat); 49301e04c3fSmrg } 494af69d88dSmrg 49501e04c3fSmrg if (!tex_format) 496af69d88dSmrg return GL_FALSE; 497af69d88dSmrg 4987ec681f3Smrg switch (t->Attrib.ImageFormatCompatibilityType) { 499af69d88dSmrg case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE: 50001e04c3fSmrg if (_mesa_get_format_bytes(tex_format) != 501af69d88dSmrg _mesa_get_format_bytes(u->_ActualFormat)) 502af69d88dSmrg return GL_FALSE; 503af69d88dSmrg break; 504af69d88dSmrg 505af69d88dSmrg case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS: 50601e04c3fSmrg if (get_image_format_class(tex_format) != 507af69d88dSmrg get_image_format_class(u->_ActualFormat)) 508af69d88dSmrg return GL_FALSE; 509af69d88dSmrg break; 510af69d88dSmrg 511af69d88dSmrg default: 512af69d88dSmrg assert(!"Unexpected image format compatibility type"); 513af69d88dSmrg } 514af69d88dSmrg 515af69d88dSmrg return GL_TRUE; 516af69d88dSmrg} 517af69d88dSmrg 518af69d88dSmrgstatic GLboolean 519af69d88dSmrgvalidate_bind_image_texture(struct gl_context *ctx, GLuint unit, 52001e04c3fSmrg GLuint texture, GLint level, GLint layer, 5217ec681f3Smrg GLenum access, GLenum format, bool check_level_layer) 522af69d88dSmrg{ 523af69d88dSmrg assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS); 524af69d88dSmrg 525af69d88dSmrg if (unit >= ctx->Const.MaxImageUnits) { 526af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(unit)"); 527af69d88dSmrg return GL_FALSE; 528af69d88dSmrg } 529af69d88dSmrg 5307ec681f3Smrg if (check_level_layer) { 5317ec681f3Smrg /* EXT_shader_image_load_store doesn't throw an error if level or 5327ec681f3Smrg * layer is negative. 5337ec681f3Smrg */ 5347ec681f3Smrg if (level < 0) { 5357ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)"); 5367ec681f3Smrg return GL_FALSE; 5377ec681f3Smrg } 538af69d88dSmrg 5397ec681f3Smrg if (layer < 0) { 5407ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)"); 5417ec681f3Smrg return GL_FALSE; 5427ec681f3Smrg } 543af69d88dSmrg } 544af69d88dSmrg 545af69d88dSmrg if (access != GL_READ_ONLY && 546af69d88dSmrg access != GL_WRITE_ONLY && 547af69d88dSmrg access != GL_READ_WRITE) { 548af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(access)"); 549af69d88dSmrg return GL_FALSE; 550af69d88dSmrg } 551af69d88dSmrg 55201e04c3fSmrg if (!_mesa_is_shader_image_format_supported(ctx, format)) { 553af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)"); 554af69d88dSmrg return GL_FALSE; 555af69d88dSmrg } 556af69d88dSmrg 557af69d88dSmrg return GL_TRUE; 558af69d88dSmrg} 559af69d88dSmrg 56001e04c3fSmrgstatic void 56101e04c3fSmrgset_image_binding(struct gl_image_unit *u, struct gl_texture_object *texObj, 56201e04c3fSmrg GLint level, GLboolean layered, GLint layer, GLenum access, 56301e04c3fSmrg GLenum format) 564af69d88dSmrg{ 56501e04c3fSmrg u->Level = level; 56601e04c3fSmrg u->Access = access; 56701e04c3fSmrg u->Format = format; 56801e04c3fSmrg u->_ActualFormat = _mesa_get_shader_image_format(format); 56901e04c3fSmrg 57001e04c3fSmrg if (texObj && _mesa_tex_target_is_layered(texObj->Target)) { 57101e04c3fSmrg u->Layered = layered; 57201e04c3fSmrg u->Layer = layer; 57301e04c3fSmrg } else { 57401e04c3fSmrg u->Layered = GL_FALSE; 57501e04c3fSmrg u->Layer = 0; 57601e04c3fSmrg } 5777ec681f3Smrg u->_Layer = (u->Layered ? 0 : u->Layer); 578af69d88dSmrg 57901e04c3fSmrg _mesa_reference_texobj(&u->TexObj, texObj); 58001e04c3fSmrg} 58101e04c3fSmrg 58201e04c3fSmrgstatic void 58301e04c3fSmrgbind_image_texture(struct gl_context *ctx, struct gl_texture_object *texObj, 58401e04c3fSmrg GLuint unit, GLint level, GLboolean layered, GLint layer, 58501e04c3fSmrg GLenum access, GLenum format) 58601e04c3fSmrg{ 58701e04c3fSmrg struct gl_image_unit *u; 588af69d88dSmrg 589af69d88dSmrg u = &ctx->ImageUnits[unit]; 590af69d88dSmrg 5917ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 592af69d88dSmrg ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; 593af69d88dSmrg 59401e04c3fSmrg set_image_binding(u, texObj, level, layered, layer, access, format); 59501e04c3fSmrg} 596af69d88dSmrg 59701e04c3fSmrgvoid GLAPIENTRY 59801e04c3fSmrg_mesa_BindImageTexture_no_error(GLuint unit, GLuint texture, GLint level, 59901e04c3fSmrg GLboolean layered, GLint layer, GLenum access, 60001e04c3fSmrg GLenum format) 60101e04c3fSmrg{ 60201e04c3fSmrg struct gl_texture_object *texObj = NULL; 603af69d88dSmrg 60401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 605af69d88dSmrg 60601e04c3fSmrg if (texture) 60701e04c3fSmrg texObj = _mesa_lookup_texture(ctx, texture); 608af69d88dSmrg 60901e04c3fSmrg bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format); 610af69d88dSmrg} 611af69d88dSmrg 612af69d88dSmrgvoid GLAPIENTRY 61301e04c3fSmrg_mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, 61401e04c3fSmrg GLboolean layered, GLint layer, GLenum access, 61501e04c3fSmrg GLenum format) 616af69d88dSmrg{ 61701e04c3fSmrg struct gl_texture_object *texObj = NULL; 61801e04c3fSmrg 619af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 620af69d88dSmrg 62101e04c3fSmrg if (!validate_bind_image_texture(ctx, unit, texture, level, layer, access, 6227ec681f3Smrg format, true)) 623af69d88dSmrg return; 624af69d88dSmrg 62501e04c3fSmrg if (texture) { 62601e04c3fSmrg texObj = _mesa_lookup_texture(ctx, texture); 62701e04c3fSmrg 62801e04c3fSmrg if (!texObj) { 62901e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)"); 63001e04c3fSmrg return; 63101e04c3fSmrg } 63201e04c3fSmrg 63301e04c3fSmrg /* From section 8.22 "Texture Image Loads and Stores" of the OpenGL ES 63401e04c3fSmrg * 3.1 spec: 635af69d88dSmrg * 63601e04c3fSmrg * "An INVALID_OPERATION error is generated if texture is not the name 63701e04c3fSmrg * of an immutable texture object." 63801e04c3fSmrg * 63901e04c3fSmrg * However note that issue 7 of the GL_OES_texture_buffer spec 64001e04c3fSmrg * recognizes that there is no way to create immutable buffer textures, 64101e04c3fSmrg * so those are excluded from this requirement. 6427ec681f3Smrg * 6437ec681f3Smrg * Additionally, issue 10 of the OES_EGL_image_external_essl3 spec 6447ec681f3Smrg * states that glBindImageTexture must accept external texture objects. 645af69d88dSmrg */ 6467ec681f3Smrg if (_mesa_is_gles(ctx) && !texObj->Immutable && !texObj->External && 64701e04c3fSmrg texObj->Target != GL_TEXTURE_BUFFER) { 64801e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 64901e04c3fSmrg "glBindImageTexture(!immutable)"); 65001e04c3fSmrg return; 65101e04c3fSmrg } 652af69d88dSmrg } 653af69d88dSmrg 65401e04c3fSmrg bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format); 65501e04c3fSmrg} 65601e04c3fSmrg 6577ec681f3Smrgvoid GLAPIENTRY 6587ec681f3Smrg_mesa_BindImageTextureEXT(GLuint index, GLuint texture, GLint level, 6597ec681f3Smrg GLboolean layered, GLint layer, GLenum access, 6607ec681f3Smrg GLint format) 6617ec681f3Smrg{ 6627ec681f3Smrg struct gl_texture_object *texObj = NULL; 6637ec681f3Smrg 6647ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 6657ec681f3Smrg 6667ec681f3Smrg if (!validate_bind_image_texture(ctx, index, texture, level, layer, access, 6677ec681f3Smrg format, false)) 6687ec681f3Smrg return; 6697ec681f3Smrg 6707ec681f3Smrg if (texture) { 6717ec681f3Smrg texObj = _mesa_lookup_texture(ctx, texture); 6727ec681f3Smrg 6737ec681f3Smrg if (!texObj) { 6747ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTextureEXT(texture)"); 6757ec681f3Smrg return; 6767ec681f3Smrg } 6777ec681f3Smrg } 6787ec681f3Smrg 6797ec681f3Smrg bind_image_texture(ctx, texObj, index, level, layered, layer, access, format); 6807ec681f3Smrg} 6817ec681f3Smrg 68201e04c3fSmrgstatic ALWAYS_INLINE void 68301e04c3fSmrgbind_image_textures(struct gl_context *ctx, GLuint first, GLuint count, 68401e04c3fSmrg const GLuint *textures, bool no_error) 68501e04c3fSmrg{ 68601e04c3fSmrg int i; 68701e04c3fSmrg 688af69d88dSmrg /* Assume that at least one binding will be changed */ 6897ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 690af69d88dSmrg ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; 691af69d88dSmrg 692af69d88dSmrg /* Note that the error semantics for multi-bind commands differ from 693af69d88dSmrg * those of other GL commands. 694af69d88dSmrg * 695af69d88dSmrg * The Issues section in the ARB_multi_bind spec says: 696af69d88dSmrg * 697af69d88dSmrg * "(11) Typically, OpenGL specifies that if an error is generated by 698af69d88dSmrg * a command, that command has no effect. This is somewhat 699af69d88dSmrg * unfortunate for multi-bind commands, because it would require 700af69d88dSmrg * a first pass to scan the entire list of bound objects for 701af69d88dSmrg * errors and then a second pass to actually perform the 702af69d88dSmrg * bindings. Should we have different error semantics? 703af69d88dSmrg * 704af69d88dSmrg * RESOLVED: Yes. In this specification, when the parameters for 705af69d88dSmrg * one of the <count> binding points are invalid, that binding 706af69d88dSmrg * point is not updated and an error will be generated. However, 707af69d88dSmrg * other binding points in the same command will be updated if 708af69d88dSmrg * their parameters are valid and no other error occurs." 709af69d88dSmrg */ 710af69d88dSmrg 71101e04c3fSmrg _mesa_HashLockMutex(ctx->Shared->TexObjects); 712af69d88dSmrg 713af69d88dSmrg for (i = 0; i < count; i++) { 714af69d88dSmrg struct gl_image_unit *u = &ctx->ImageUnits[first + i]; 715af69d88dSmrg const GLuint texture = textures ? textures[i] : 0; 716af69d88dSmrg 71701e04c3fSmrg if (texture) { 71801e04c3fSmrg struct gl_texture_object *texObj = u->TexObj; 71901e04c3fSmrg GLenum tex_format; 720af69d88dSmrg 72101e04c3fSmrg if (!texObj || texObj->Name != texture) { 722af69d88dSmrg texObj = _mesa_lookup_texture_locked(ctx, texture); 72301e04c3fSmrg if (!no_error && !texObj) { 724af69d88dSmrg /* The ARB_multi_bind spec says: 725af69d88dSmrg * 726af69d88dSmrg * "An INVALID_OPERATION error is generated if any value 727af69d88dSmrg * in <textures> is not zero or the name of an existing 728af69d88dSmrg * texture object (per binding)." 729af69d88dSmrg */ 730af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 731af69d88dSmrg "glBindImageTextures(textures[%d]=%u " 732af69d88dSmrg "is not zero or the name of an existing texture " 733af69d88dSmrg "object)", i, texture); 734af69d88dSmrg continue; 735af69d88dSmrg } 736af69d88dSmrg } 737af69d88dSmrg 73801e04c3fSmrg if (texObj->Target == GL_TEXTURE_BUFFER) { 73901e04c3fSmrg tex_format = texObj->BufferObjectFormat; 74001e04c3fSmrg } else { 74101e04c3fSmrg struct gl_texture_image *image = texObj->Image[0][0]; 742af69d88dSmrg 74301e04c3fSmrg if (!no_error && (!image || image->Width == 0 || 74401e04c3fSmrg image->Height == 0 || image->Depth == 0)) { 74501e04c3fSmrg /* The ARB_multi_bind spec says: 74601e04c3fSmrg * 74701e04c3fSmrg * "An INVALID_OPERATION error is generated if the width, 74801e04c3fSmrg * height, or depth of the level zero texture image of 74901e04c3fSmrg * any texture in <textures> is zero (per binding)." 75001e04c3fSmrg */ 75101e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 75201e04c3fSmrg "glBindImageTextures(the width, height or depth " 75301e04c3fSmrg "of the level zero texture image of " 75401e04c3fSmrg "textures[%d]=%u is zero)", i, texture); 75501e04c3fSmrg continue; 75601e04c3fSmrg } 757af69d88dSmrg 75801e04c3fSmrg tex_format = image->InternalFormat; 75901e04c3fSmrg } 760af69d88dSmrg 76101e04c3fSmrg if (!no_error && 76201e04c3fSmrg !_mesa_is_shader_image_format_supported(ctx, tex_format)) { 763af69d88dSmrg /* The ARB_multi_bind spec says: 764af69d88dSmrg * 765af69d88dSmrg * "An INVALID_OPERATION error is generated if the internal 766af69d88dSmrg * format of the level zero texture image of any texture 767af69d88dSmrg * in <textures> is not found in table 8.33 (per binding)." 768af69d88dSmrg */ 769af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 770af69d88dSmrg "glBindImageTextures(the internal format %s of " 771af69d88dSmrg "the level zero texture image of textures[%d]=%u " 772af69d88dSmrg "is not supported)", 77301e04c3fSmrg _mesa_enum_to_string(tex_format), 774af69d88dSmrg i, texture); 775af69d88dSmrg continue; 776af69d88dSmrg } 777af69d88dSmrg 778af69d88dSmrg /* Update the texture binding */ 77901e04c3fSmrg set_image_binding(u, texObj, 0, 78001e04c3fSmrg _mesa_tex_target_is_layered(texObj->Target), 78101e04c3fSmrg 0, GL_READ_WRITE, tex_format); 782af69d88dSmrg } else { 783af69d88dSmrg /* Unbind the texture from the unit */ 78401e04c3fSmrg set_image_binding(u, NULL, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); 785af69d88dSmrg } 786af69d88dSmrg } 787af69d88dSmrg 78801e04c3fSmrg _mesa_HashUnlockMutex(ctx->Shared->TexObjects); 78901e04c3fSmrg} 79001e04c3fSmrg 79101e04c3fSmrgvoid GLAPIENTRY 79201e04c3fSmrg_mesa_BindImageTextures_no_error(GLuint first, GLsizei count, 79301e04c3fSmrg const GLuint *textures) 79401e04c3fSmrg{ 79501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 79601e04c3fSmrg 79701e04c3fSmrg bind_image_textures(ctx, first, count, textures, true); 798af69d88dSmrg} 799af69d88dSmrg 800af69d88dSmrgvoid GLAPIENTRY 80101e04c3fSmrg_mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) 802af69d88dSmrg{ 803af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 804af69d88dSmrg 80501e04c3fSmrg if (!ctx->Extensions.ARB_shader_image_load_store) { 80601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTextures()"); 80701e04c3fSmrg return; 80801e04c3fSmrg } 80901e04c3fSmrg 81001e04c3fSmrg if (first + count > ctx->Const.MaxImageUnits) { 81101e04c3fSmrg /* The ARB_multi_bind spec says: 81201e04c3fSmrg * 81301e04c3fSmrg * "An INVALID_OPERATION error is generated if <first> + <count> 81401e04c3fSmrg * is greater than the number of image units supported by 81501e04c3fSmrg * the implementation." 81601e04c3fSmrg */ 81701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 81801e04c3fSmrg "glBindImageTextures(first=%u + count=%d > the value of " 81901e04c3fSmrg "GL_MAX_IMAGE_UNITS=%u)", 82001e04c3fSmrg first, count, ctx->Const.MaxImageUnits); 82101e04c3fSmrg return; 82201e04c3fSmrg } 82301e04c3fSmrg 82401e04c3fSmrg bind_image_textures(ctx, first, count, textures, false); 825af69d88dSmrg} 826