| 1 | /* |
| 2 | * Copyright (C) 2010, 2016 Apple Inc. All rights reserved. |
| 3 | * Copyright (C) 2010 Google Inc. All rights reserved. |
| 4 | * Copyright (C) 2010 Mozilla Corporation. All rights reserved. |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: |
| 9 | * 1. Redistributions of source code must retain the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer. |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in the |
| 13 | * documentation and/or other materials provided with the distribution. |
| 14 | * |
| 15 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 18 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 22 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 23 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | #include "config.h" |
| 29 | |
| 30 | #if ENABLE(GRAPHICS_CONTEXT_3D) |
| 31 | |
| 32 | #include "GraphicsContext3D.h" |
| 33 | |
| 34 | #include "Extensions3D.h" |
| 35 | #include "FormatConverter.h" |
| 36 | #include "Image.h" |
| 37 | #include "ImageData.h" |
| 38 | #include "ImageObserver.h" |
| 39 | #include <wtf/UniqueArray.h> |
| 40 | |
| 41 | namespace WebCore { |
| 42 | |
| 43 | namespace { |
| 44 | |
| 45 | GraphicsContext3D::DataFormat getDataFormat(GC3Denum destinationFormat, GC3Denum destinationType) |
| 46 | { |
| 47 | GraphicsContext3D::DataFormat dstFormat = GraphicsContext3D::DataFormatRGBA8; |
| 48 | switch (destinationType) { |
| 49 | case GraphicsContext3D::UNSIGNED_BYTE: |
| 50 | switch (destinationFormat) { |
| 51 | case GraphicsContext3D::RGB: |
| 52 | dstFormat = GraphicsContext3D::DataFormatRGB8; |
| 53 | break; |
| 54 | case GraphicsContext3D::RGBA: |
| 55 | dstFormat = GraphicsContext3D::DataFormatRGBA8; |
| 56 | break; |
| 57 | case GraphicsContext3D::ALPHA: |
| 58 | dstFormat = GraphicsContext3D::DataFormatA8; |
| 59 | break; |
| 60 | case GraphicsContext3D::LUMINANCE: |
| 61 | dstFormat = GraphicsContext3D::DataFormatR8; |
| 62 | break; |
| 63 | case GraphicsContext3D::LUMINANCE_ALPHA: |
| 64 | dstFormat = GraphicsContext3D::DataFormatRA8; |
| 65 | break; |
| 66 | case GraphicsContext3D::SRGB: |
| 67 | dstFormat = GraphicsContext3D::DataFormatRGB8; |
| 68 | break; |
| 69 | case GraphicsContext3D::SRGB_ALPHA: |
| 70 | dstFormat = GraphicsContext3D::DataFormatRGBA8; |
| 71 | break; |
| 72 | default: |
| 73 | ASSERT_NOT_REACHED(); |
| 74 | } |
| 75 | break; |
| 76 | case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: |
| 77 | dstFormat = GraphicsContext3D::DataFormatRGBA4444; |
| 78 | break; |
| 79 | case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: |
| 80 | dstFormat = GraphicsContext3D::DataFormatRGBA5551; |
| 81 | break; |
| 82 | case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: |
| 83 | dstFormat = GraphicsContext3D::DataFormatRGB565; |
| 84 | break; |
| 85 | case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float |
| 86 | switch (destinationFormat) { |
| 87 | case GraphicsContext3D::RGB: |
| 88 | dstFormat = GraphicsContext3D::DataFormatRGB16F; |
| 89 | break; |
| 90 | case GraphicsContext3D::RGBA: |
| 91 | dstFormat = GraphicsContext3D::DataFormatRGBA16F; |
| 92 | break; |
| 93 | case GraphicsContext3D::ALPHA: |
| 94 | dstFormat = GraphicsContext3D::DataFormatA16F; |
| 95 | break; |
| 96 | case GraphicsContext3D::LUMINANCE: |
| 97 | dstFormat = GraphicsContext3D::DataFormatR16F; |
| 98 | break; |
| 99 | case GraphicsContext3D::LUMINANCE_ALPHA: |
| 100 | dstFormat = GraphicsContext3D::DataFormatRA16F; |
| 101 | break; |
| 102 | case GraphicsContext3D::SRGB: |
| 103 | dstFormat = GraphicsContext3D::DataFormatRGB16F; |
| 104 | break; |
| 105 | case GraphicsContext3D::SRGB_ALPHA: |
| 106 | dstFormat = GraphicsContext3D::DataFormatRGBA16F; |
| 107 | break; |
| 108 | default: |
| 109 | ASSERT_NOT_REACHED(); |
| 110 | } |
| 111 | break; |
| 112 | case GraphicsContext3D::FLOAT: // OES_texture_float |
| 113 | switch (destinationFormat) { |
| 114 | case GraphicsContext3D::RGB: |
| 115 | dstFormat = GraphicsContext3D::DataFormatRGB32F; |
| 116 | break; |
| 117 | case GraphicsContext3D::RGBA: |
| 118 | dstFormat = GraphicsContext3D::DataFormatRGBA32F; |
| 119 | break; |
| 120 | case GraphicsContext3D::ALPHA: |
| 121 | dstFormat = GraphicsContext3D::DataFormatA32F; |
| 122 | break; |
| 123 | case GraphicsContext3D::LUMINANCE: |
| 124 | dstFormat = GraphicsContext3D::DataFormatR32F; |
| 125 | break; |
| 126 | case GraphicsContext3D::LUMINANCE_ALPHA: |
| 127 | dstFormat = GraphicsContext3D::DataFormatRA32F; |
| 128 | break; |
| 129 | case GraphicsContext3D::SRGB: |
| 130 | dstFormat = GraphicsContext3D::DataFormatRGB32F; |
| 131 | break; |
| 132 | case GraphicsContext3D::SRGB_ALPHA: |
| 133 | dstFormat = GraphicsContext3D::DataFormatRGBA32F; |
| 134 | break; |
| 135 | default: |
| 136 | ASSERT_NOT_REACHED(); |
| 137 | } |
| 138 | break; |
| 139 | default: |
| 140 | ASSERT_NOT_REACHED(); |
| 141 | } |
| 142 | return dstFormat; |
| 143 | } |
| 144 | |
| 145 | } // anonymous namespace |
| 146 | |
| 147 | bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment) |
| 148 | { |
| 149 | ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8); |
| 150 | UniqueArray<unsigned char> zero; |
| 151 | if (width > 0 && height > 0) { |
| 152 | unsigned int size; |
| 153 | GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, nullptr); |
| 154 | if (error != GraphicsContext3D::NO_ERROR) { |
| 155 | synthesizeGLError(error); |
| 156 | return false; |
| 157 | } |
| 158 | zero = makeUniqueArray<unsigned char>(size); |
| 159 | if (!zero) { |
| 160 | synthesizeGLError(GraphicsContext3D::INVALID_VALUE); |
| 161 | return false; |
| 162 | } |
| 163 | memset(zero.get(), 0, size); |
| 164 | } |
| 165 | return texImage2D(target, level, internalformat, width, height, border, format, type, zero.get()); |
| 166 | } |
| 167 | |
| 168 | bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format, GC3Denum type, unsigned int* componentsPerPixel, unsigned int* bytesPerComponent) |
| 169 | { |
| 170 | switch (format) { |
| 171 | case GraphicsContext3D::RED: |
| 172 | case GraphicsContext3D::RED_INTEGER: |
| 173 | case GraphicsContext3D::ALPHA: |
| 174 | case GraphicsContext3D::LUMINANCE: |
| 175 | case GraphicsContext3D::DEPTH_COMPONENT: |
| 176 | case GraphicsContext3D::DEPTH_STENCIL: |
| 177 | *componentsPerPixel = 1; |
| 178 | break; |
| 179 | case GraphicsContext3D::RG: |
| 180 | case GraphicsContext3D::RG_INTEGER: |
| 181 | case GraphicsContext3D::LUMINANCE_ALPHA: |
| 182 | *componentsPerPixel = 2; |
| 183 | break; |
| 184 | case GraphicsContext3D::RGB: |
| 185 | case GraphicsContext3D::RGB_INTEGER: |
| 186 | case Extensions3D::SRGB_EXT: |
| 187 | *componentsPerPixel = 3; |
| 188 | break; |
| 189 | case GraphicsContext3D::RGBA: |
| 190 | case GraphicsContext3D::RGBA_INTEGER: |
| 191 | case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888 |
| 192 | case Extensions3D::SRGB_ALPHA_EXT: |
| 193 | *componentsPerPixel = 4; |
| 194 | break; |
| 195 | default: |
| 196 | return false; |
| 197 | } |
| 198 | |
| 199 | switch (type) { |
| 200 | case GraphicsContext3D::UNSIGNED_BYTE: |
| 201 | *bytesPerComponent = sizeof(GC3Dubyte); |
| 202 | break; |
| 203 | case GraphicsContext3D::BYTE: |
| 204 | *bytesPerComponent = sizeof(GC3Dbyte); |
| 205 | break; |
| 206 | case GraphicsContext3D::UNSIGNED_SHORT: |
| 207 | *bytesPerComponent = sizeof(GC3Dushort); |
| 208 | break; |
| 209 | case GraphicsContext3D::SHORT: |
| 210 | *bytesPerComponent = sizeof(GC3Dshort); |
| 211 | break; |
| 212 | case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: |
| 213 | case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: |
| 214 | case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: |
| 215 | *componentsPerPixel = 1; |
| 216 | *bytesPerComponent = sizeof(GC3Dushort); |
| 217 | break; |
| 218 | case GraphicsContext3D::UNSIGNED_INT_24_8: |
| 219 | case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV: |
| 220 | case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV: |
| 221 | case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV: |
| 222 | *componentsPerPixel = 1; |
| 223 | *bytesPerComponent = sizeof(GC3Duint); |
| 224 | break; |
| 225 | case GraphicsContext3D::UNSIGNED_INT: |
| 226 | *bytesPerComponent = sizeof(GC3Duint); |
| 227 | break; |
| 228 | case GraphicsContext3D::INT: |
| 229 | *bytesPerComponent = sizeof(GC3Dint); |
| 230 | break; |
| 231 | case GraphicsContext3D::FLOAT: // OES_texture_float |
| 232 | *bytesPerComponent = sizeof(GC3Dfloat); |
| 233 | break; |
| 234 | case GraphicsContext3D::HALF_FLOAT: |
| 235 | case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float |
| 236 | *bytesPerComponent = sizeof(GC3Dhalffloat); |
| 237 | break; |
| 238 | case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV: |
| 239 | *bytesPerComponent = sizeof(GC3Dfloat) + sizeof(GC3Duint); |
| 240 | break; |
| 241 | default: |
| 242 | return false; |
| 243 | } |
| 244 | return true; |
| 245 | } |
| 246 | |
| 247 | bool GraphicsContext3D::possibleFormatAndTypeForInternalFormat(GC3Denum internalFormat, GC3Denum& format, GC3Denum& type) |
| 248 | { |
| 249 | #define POSSIBLE_FORMAT_TYPE_CASE(internalFormatMacro, formatMacro, typeMacro) case internalFormatMacro: \ |
| 250 | format = formatMacro; \ |
| 251 | type = GraphicsContext3D::typeMacro; \ |
| 252 | break; |
| 253 | |
| 254 | switch (internalFormat) { |
| 255 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB , GraphicsContext3D::RGB , UNSIGNED_BYTE ); |
| 256 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA , GraphicsContext3D::RGBA , UNSIGNED_BYTE ); |
| 257 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::LUMINANCE_ALPHA , GraphicsContext3D::LUMINANCE_ALPHA, UNSIGNED_BYTE ); |
| 258 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::LUMINANCE , GraphicsContext3D::LUMINANCE , UNSIGNED_BYTE ); |
| 259 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::ALPHA , GraphicsContext3D::ALPHA , UNSIGNED_BYTE ); |
| 260 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8 , GraphicsContext3D::RED , UNSIGNED_BYTE ); |
| 261 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8_SNORM , GraphicsContext3D::RED , BYTE ); |
| 262 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16F , GraphicsContext3D::RED , HALF_FLOAT ); |
| 263 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32F , GraphicsContext3D::RED , FLOAT ); |
| 264 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8UI , GraphicsContext3D::RED_INTEGER , UNSIGNED_BYTE ); |
| 265 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8I , GraphicsContext3D::RED_INTEGER , BYTE ); |
| 266 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16UI , GraphicsContext3D::RED_INTEGER , UNSIGNED_SHORT ); |
| 267 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16I , GraphicsContext3D::RED_INTEGER , SHORT ); |
| 268 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32UI , GraphicsContext3D::RED_INTEGER , UNSIGNED_INT ); |
| 269 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32I , GraphicsContext3D::RED_INTEGER , INT ); |
| 270 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8 , GraphicsContext3D::RG , UNSIGNED_BYTE ); |
| 271 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8_SNORM , GraphicsContext3D::RG , BYTE ); |
| 272 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16F , GraphicsContext3D::RG , HALF_FLOAT ); |
| 273 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32F , GraphicsContext3D::RG , FLOAT ); |
| 274 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8UI , GraphicsContext3D::RG_INTEGER , UNSIGNED_BYTE ); |
| 275 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8I , GraphicsContext3D::RG_INTEGER , BYTE ); |
| 276 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16UI , GraphicsContext3D::RG_INTEGER , UNSIGNED_SHORT ); |
| 277 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16I , GraphicsContext3D::RG_INTEGER , SHORT ); |
| 278 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32UI , GraphicsContext3D::RG_INTEGER , UNSIGNED_INT ); |
| 279 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32I , GraphicsContext3D::RG_INTEGER , INT ); |
| 280 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8 , GraphicsContext3D::RGB , UNSIGNED_BYTE ); |
| 281 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::SRGB8 , GraphicsContext3D::RGB , UNSIGNED_BYTE ); |
| 282 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB565 , GraphicsContext3D::RGB , UNSIGNED_SHORT_5_6_5 ); |
| 283 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8_SNORM , GraphicsContext3D::RGB , BYTE ); |
| 284 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R11F_G11F_B10F , GraphicsContext3D::RGB , UNSIGNED_INT_10F_11F_11F_REV ); |
| 285 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB9_E5 , GraphicsContext3D::RGB , UNSIGNED_INT_5_9_9_9_REV ); |
| 286 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16F , GraphicsContext3D::RGB , HALF_FLOAT ); |
| 287 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32F , GraphicsContext3D::RGB , FLOAT ); |
| 288 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8UI , GraphicsContext3D::RGB_INTEGER , UNSIGNED_BYTE ); |
| 289 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8I , GraphicsContext3D::RGB_INTEGER , BYTE ); |
| 290 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16UI , GraphicsContext3D::RGB_INTEGER , UNSIGNED_SHORT ); |
| 291 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16I , GraphicsContext3D::RGB_INTEGER , SHORT ); |
| 292 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32UI , GraphicsContext3D::RGB_INTEGER , UNSIGNED_INT ); |
| 293 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32I , GraphicsContext3D::RGB_INTEGER , INT ); |
| 294 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8 , GraphicsContext3D::RGBA , UNSIGNED_BYTE ); |
| 295 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::SRGB8_ALPHA8 , GraphicsContext3D::RGBA , UNSIGNED_BYTE ); |
| 296 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8_SNORM , GraphicsContext3D::RGBA , BYTE ); |
| 297 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB5_A1 , GraphicsContext3D::RGBA , UNSIGNED_SHORT_5_5_5_1 ); |
| 298 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA4 , GraphicsContext3D::RGBA , UNSIGNED_SHORT_4_4_4_4 ); |
| 299 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB10_A2 , GraphicsContext3D::RGBA , UNSIGNED_INT_2_10_10_10_REV ); |
| 300 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16F , GraphicsContext3D::RGBA , HALF_FLOAT ); |
| 301 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32F , GraphicsContext3D::RGBA , FLOAT ); |
| 302 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8UI , GraphicsContext3D::RGBA_INTEGER , UNSIGNED_BYTE ); |
| 303 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8I , GraphicsContext3D::RGBA_INTEGER , BYTE ); |
| 304 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB10_A2UI , GraphicsContext3D::RGBA_INTEGER , UNSIGNED_INT_2_10_10_10_REV ); |
| 305 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16UI , GraphicsContext3D::RGBA_INTEGER , UNSIGNED_SHORT ); |
| 306 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16I , GraphicsContext3D::RGBA_INTEGER , SHORT ); |
| 307 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32I , GraphicsContext3D::RGBA_INTEGER , INT ); |
| 308 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32UI , GraphicsContext3D::RGBA_INTEGER , UNSIGNED_INT ); |
| 309 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT16 , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_SHORT ); |
| 310 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_SHORT ); |
| 311 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT24 , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_INT ); |
| 312 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT32F, GraphicsContext3D::DEPTH_COMPONENT, FLOAT ); |
| 313 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_STENCIL , GraphicsContext3D::DEPTH_STENCIL , UNSIGNED_INT_24_8 ); |
| 314 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH24_STENCIL8 , GraphicsContext3D::DEPTH_STENCIL , UNSIGNED_INT_24_8 ); |
| 315 | POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH32F_STENCIL8 , GraphicsContext3D::DEPTH_STENCIL , FLOAT_32_UNSIGNED_INT_24_8_REV); |
| 316 | POSSIBLE_FORMAT_TYPE_CASE(Extensions3D::SRGB_EXT , Extensions3D::SRGB_EXT , UNSIGNED_BYTE ); |
| 317 | POSSIBLE_FORMAT_TYPE_CASE(Extensions3D::SRGB_ALPHA_EXT , Extensions3D::SRGB_ALPHA_EXT , UNSIGNED_BYTE ); |
| 318 | default: |
| 319 | return false; |
| 320 | } |
| 321 | #undef POSSIBLE_FORMAT_TYPE_CASE |
| 322 | |
| 323 | return true; |
| 324 | } |
| 325 | |
| 326 | GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment, unsigned int* imageSizeInBytes, unsigned int* paddingInBytes) |
| 327 | { |
| 328 | ASSERT(imageSizeInBytes); |
| 329 | ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8); |
| 330 | if (width < 0 || height < 0) |
| 331 | return GraphicsContext3D::INVALID_VALUE; |
| 332 | unsigned int bytesPerComponent, componentsPerPixel; |
| 333 | if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) |
| 334 | return GraphicsContext3D::INVALID_ENUM; |
| 335 | if (!width || !height) { |
| 336 | *imageSizeInBytes = 0; |
| 337 | if (paddingInBytes) |
| 338 | *paddingInBytes = 0; |
| 339 | return GraphicsContext3D::NO_ERROR; |
| 340 | } |
| 341 | Checked<uint32_t, RecordOverflow> checkedValue = bytesPerComponent * componentsPerPixel; |
| 342 | checkedValue *= width; |
| 343 | if (checkedValue.hasOverflowed()) |
| 344 | return GraphicsContext3D::INVALID_VALUE; |
| 345 | unsigned int validRowSize = checkedValue.unsafeGet(); |
| 346 | unsigned int padding = 0; |
| 347 | unsigned int residual = validRowSize % alignment; |
| 348 | if (residual) { |
| 349 | padding = alignment - residual; |
| 350 | checkedValue += padding; |
| 351 | } |
| 352 | // Last row needs no padding. |
| 353 | checkedValue *= (height - 1); |
| 354 | checkedValue += validRowSize; |
| 355 | if (checkedValue.hasOverflowed()) |
| 356 | return GraphicsContext3D::INVALID_VALUE; |
| 357 | *imageSizeInBytes = checkedValue.unsafeGet(); |
| 358 | if (paddingInBytes) |
| 359 | *paddingInBytes = padding; |
| 360 | return GraphicsContext3D::NO_ERROR; |
| 361 | } |
| 362 | |
| 363 | GraphicsContext3D::ImageExtractor::(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile) |
| 364 | { |
| 365 | m_image = image; |
| 366 | m_imageHtmlDomSource = imageHtmlDomSource; |
| 367 | m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile); |
| 368 | } |
| 369 | |
| 370 | bool GraphicsContext3D::packImageData(Image* image, const void* pixels, GC3Denum format, GC3Denum type, bool flipY, AlphaOp alphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data) |
| 371 | { |
| 372 | if (!image || !pixels) |
| 373 | return false; |
| 374 | |
| 375 | unsigned packedSize; |
| 376 | // Output data is tightly packed (alignment == 1). |
| 377 | if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, nullptr) != GraphicsContext3D::NO_ERROR) |
| 378 | return false; |
| 379 | data.resize(packedSize); |
| 380 | |
| 381 | if (!packPixels(reinterpret_cast<const uint8_t*>(pixels), sourceFormat, width, height, sourceUnpackAlignment, format, type, alphaOp, data.data(), flipY)) |
| 382 | return false; |
| 383 | if (ImageObserver* observer = image->imageObserver()) |
| 384 | observer->didDraw(*image); |
| 385 | return true; |
| 386 | } |
| 387 | |
| 388 | bool GraphicsContext3D::(ImageData* imageData, GC3Denum format, GC3Denum type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data) |
| 389 | { |
| 390 | if (!imageData) |
| 391 | return false; |
| 392 | int width = imageData->width(); |
| 393 | int height = imageData->height(); |
| 394 | |
| 395 | unsigned int packedSize; |
| 396 | // Output data is tightly packed (alignment == 1). |
| 397 | if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, nullptr) != GraphicsContext3D::NO_ERROR) |
| 398 | return false; |
| 399 | data.resize(packedSize); |
| 400 | |
| 401 | if (!packPixels(imageData->data()->data(), DataFormatRGBA8, width, height, 0, format, type, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing, data.data(), flipY)) |
| 402 | return false; |
| 403 | |
| 404 | return true; |
| 405 | } |
| 406 | |
| 407 | bool GraphicsContext3D::(unsigned int width, unsigned int height, GC3Denum format, GC3Denum type, unsigned int unpackAlignment, bool flipY, bool premultiplyAlpha, const void* pixels, Vector<uint8_t>& data) |
| 408 | { |
| 409 | // Assumes format, type, etc. have already been validated. |
| 410 | DataFormat sourceDataFormat = getDataFormat(format, type); |
| 411 | |
| 412 | // Resize the output buffer. |
| 413 | unsigned int componentsPerPixel, bytesPerComponent; |
| 414 | if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) |
| 415 | return false; |
| 416 | unsigned int bytesPerPixel = componentsPerPixel * bytesPerComponent; |
| 417 | data.resize(width * height * bytesPerPixel); |
| 418 | |
| 419 | if (!packPixels(static_cast<const uint8_t*>(pixels), sourceDataFormat, width, height, unpackAlignment, format, type, (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing), data.data(), flipY)) |
| 420 | return false; |
| 421 | |
| 422 | return true; |
| 423 | } |
| 424 | |
| 425 | ALWAYS_INLINE unsigned TexelBytesForFormat(GraphicsContext3D::DataFormat format) |
| 426 | { |
| 427 | switch (format) { |
| 428 | case GraphicsContext3D::DataFormatR8: |
| 429 | case GraphicsContext3D::DataFormatA8: |
| 430 | return 1; |
| 431 | case GraphicsContext3D::DataFormatRA8: |
| 432 | case GraphicsContext3D::DataFormatAR8: |
| 433 | case GraphicsContext3D::DataFormatRGBA5551: |
| 434 | case GraphicsContext3D::DataFormatRGBA4444: |
| 435 | case GraphicsContext3D::DataFormatRGB565: |
| 436 | case GraphicsContext3D::DataFormatA16F: |
| 437 | case GraphicsContext3D::DataFormatR16F: |
| 438 | return 2; |
| 439 | case GraphicsContext3D::DataFormatRGB8: |
| 440 | case GraphicsContext3D::DataFormatBGR8: |
| 441 | return 3; |
| 442 | case GraphicsContext3D::DataFormatRGBA8: |
| 443 | case GraphicsContext3D::DataFormatARGB8: |
| 444 | case GraphicsContext3D::DataFormatABGR8: |
| 445 | case GraphicsContext3D::DataFormatBGRA8: |
| 446 | case GraphicsContext3D::DataFormatR32F: |
| 447 | case GraphicsContext3D::DataFormatA32F: |
| 448 | case GraphicsContext3D::DataFormatRA16F: |
| 449 | return 4; |
| 450 | case GraphicsContext3D::DataFormatRGB16F: |
| 451 | return 6; |
| 452 | case GraphicsContext3D::DataFormatRA32F: |
| 453 | case GraphicsContext3D::DataFormatRGBA16F: |
| 454 | return 8; |
| 455 | case GraphicsContext3D::DataFormatRGB32F: |
| 456 | return 12; |
| 457 | case GraphicsContext3D::DataFormatRGBA32F: |
| 458 | return 16; |
| 459 | default: |
| 460 | return 0; |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | bool GraphicsContext3D::packPixels(const uint8_t* sourceData, DataFormat sourceDataFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, unsigned destinationFormat, unsigned destinationType, AlphaOp alphaOp, void* destinationData, bool flipY) |
| 465 | { |
| 466 | int validSrc = width * TexelBytesForFormat(sourceDataFormat); |
| 467 | int remainder = sourceUnpackAlignment ? (validSrc % sourceUnpackAlignment) : 0; |
| 468 | int srcStride = remainder ? (validSrc + sourceUnpackAlignment - remainder) : validSrc; |
| 469 | |
| 470 | // FIXME: Implement packing pixels to WebGL 2 formats |
| 471 | switch (destinationFormat) { |
| 472 | case GraphicsContext3D::RED: |
| 473 | case GraphicsContext3D::RED_INTEGER: |
| 474 | case GraphicsContext3D::RG: |
| 475 | case GraphicsContext3D::RG_INTEGER: |
| 476 | case GraphicsContext3D::RGB_INTEGER: |
| 477 | case GraphicsContext3D::RGBA_INTEGER: |
| 478 | case GraphicsContext3D::DEPTH_COMPONENT: |
| 479 | case GraphicsContext3D::DEPTH_STENCIL: |
| 480 | return false; |
| 481 | } |
| 482 | switch (destinationType) { |
| 483 | case GraphicsContext3D::BYTE: |
| 484 | case GraphicsContext3D::SHORT: |
| 485 | case GraphicsContext3D::INT: |
| 486 | case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV: |
| 487 | case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV: |
| 488 | case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV: |
| 489 | case GraphicsContext3D::UNSIGNED_INT_24_8: |
| 490 | return false; |
| 491 | } |
| 492 | |
| 493 | DataFormat dstDataFormat = getDataFormat(destinationFormat, destinationType); |
| 494 | int dstStride = width * TexelBytesForFormat(dstDataFormat); |
| 495 | if (flipY) { |
| 496 | destinationData = static_cast<uint8_t*>(destinationData) + dstStride*(height - 1); |
| 497 | dstStride = -dstStride; |
| 498 | } |
| 499 | if (!hasAlpha(sourceDataFormat) || !hasColor(sourceDataFormat) || !hasColor(dstDataFormat)) |
| 500 | alphaOp = AlphaDoNothing; |
| 501 | |
| 502 | if (sourceDataFormat == dstDataFormat && alphaOp == AlphaDoNothing) { |
| 503 | const uint8_t* ptr = sourceData; |
| 504 | const uint8_t* ptrEnd = sourceData + srcStride * height; |
| 505 | unsigned rowSize = (dstStride > 0) ? dstStride: -dstStride; |
| 506 | uint8_t* dst = static_cast<uint8_t*>(destinationData); |
| 507 | while (ptr < ptrEnd) { |
| 508 | memcpy(dst, ptr, rowSize); |
| 509 | ptr += srcStride; |
| 510 | dst += dstStride; |
| 511 | } |
| 512 | return true; |
| 513 | } |
| 514 | |
| 515 | FormatConverter converter(width, height, sourceData, destinationData, srcStride, dstStride); |
| 516 | converter.convert(sourceDataFormat, dstDataFormat, alphaOp); |
| 517 | if (!converter.success()) |
| 518 | return false; |
| 519 | return true; |
| 520 | } |
| 521 | |
| 522 | unsigned GraphicsContext3D::getClearBitsByAttachmentType(GC3Denum attachment) |
| 523 | { |
| 524 | switch (attachment) { |
| 525 | case GraphicsContext3D::COLOR_ATTACHMENT0: |
| 526 | case Extensions3D::COLOR_ATTACHMENT1_EXT: |
| 527 | case Extensions3D::COLOR_ATTACHMENT2_EXT: |
| 528 | case Extensions3D::COLOR_ATTACHMENT3_EXT: |
| 529 | case Extensions3D::COLOR_ATTACHMENT4_EXT: |
| 530 | case Extensions3D::COLOR_ATTACHMENT5_EXT: |
| 531 | case Extensions3D::COLOR_ATTACHMENT6_EXT: |
| 532 | case Extensions3D::COLOR_ATTACHMENT7_EXT: |
| 533 | case Extensions3D::COLOR_ATTACHMENT8_EXT: |
| 534 | case Extensions3D::COLOR_ATTACHMENT9_EXT: |
| 535 | case Extensions3D::COLOR_ATTACHMENT10_EXT: |
| 536 | case Extensions3D::COLOR_ATTACHMENT11_EXT: |
| 537 | case Extensions3D::COLOR_ATTACHMENT12_EXT: |
| 538 | case Extensions3D::COLOR_ATTACHMENT13_EXT: |
| 539 | case Extensions3D::COLOR_ATTACHMENT14_EXT: |
| 540 | case Extensions3D::COLOR_ATTACHMENT15_EXT: |
| 541 | return GraphicsContext3D::COLOR_BUFFER_BIT; |
| 542 | case GraphicsContext3D::DEPTH_ATTACHMENT: |
| 543 | return GraphicsContext3D::DEPTH_BUFFER_BIT; |
| 544 | case GraphicsContext3D::STENCIL_ATTACHMENT: |
| 545 | return GraphicsContext3D::STENCIL_BUFFER_BIT; |
| 546 | case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: |
| 547 | return GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT; |
| 548 | default: |
| 549 | return 0; |
| 550 | } |
| 551 | } |
| 552 | |
| 553 | unsigned GraphicsContext3D::getClearBitsByFormat(GC3Denum format) |
| 554 | { |
| 555 | switch (format) { |
| 556 | case GraphicsContext3D::RGB: |
| 557 | case GraphicsContext3D::RGBA: |
| 558 | case GraphicsContext3D::LUMINANCE_ALPHA: |
| 559 | case GraphicsContext3D::LUMINANCE: |
| 560 | case GraphicsContext3D::ALPHA: |
| 561 | case GraphicsContext3D::R8: |
| 562 | case GraphicsContext3D::R8_SNORM: |
| 563 | case GraphicsContext3D::R16F: |
| 564 | case GraphicsContext3D::R32F: |
| 565 | case GraphicsContext3D::R8UI: |
| 566 | case GraphicsContext3D::R8I: |
| 567 | case GraphicsContext3D::R16UI: |
| 568 | case GraphicsContext3D::R16I: |
| 569 | case GraphicsContext3D::R32UI: |
| 570 | case GraphicsContext3D::R32I: |
| 571 | case GraphicsContext3D::RG8: |
| 572 | case GraphicsContext3D::RG8_SNORM: |
| 573 | case GraphicsContext3D::RG16F: |
| 574 | case GraphicsContext3D::RG32F: |
| 575 | case GraphicsContext3D::RG8UI: |
| 576 | case GraphicsContext3D::RG8I: |
| 577 | case GraphicsContext3D::RG16UI: |
| 578 | case GraphicsContext3D::RG16I: |
| 579 | case GraphicsContext3D::RG32UI: |
| 580 | case GraphicsContext3D::RG32I: |
| 581 | case GraphicsContext3D::RGB8: |
| 582 | case GraphicsContext3D::SRGB8: |
| 583 | case GraphicsContext3D::RGB565: |
| 584 | case GraphicsContext3D::RGB8_SNORM: |
| 585 | case GraphicsContext3D::R11F_G11F_B10F: |
| 586 | case GraphicsContext3D::RGB9_E5: |
| 587 | case GraphicsContext3D::RGB16F: |
| 588 | case GraphicsContext3D::RGB32F: |
| 589 | case GraphicsContext3D::RGB8UI: |
| 590 | case GraphicsContext3D::RGB8I: |
| 591 | case GraphicsContext3D::RGB16UI: |
| 592 | case GraphicsContext3D::RGB16I: |
| 593 | case GraphicsContext3D::RGB32UI: |
| 594 | case GraphicsContext3D::RGB32I: |
| 595 | case GraphicsContext3D::RGBA8: |
| 596 | case GraphicsContext3D::SRGB8_ALPHA8: |
| 597 | case GraphicsContext3D::RGBA8_SNORM: |
| 598 | case GraphicsContext3D::RGB5_A1: |
| 599 | case GraphicsContext3D::RGBA4: |
| 600 | case GraphicsContext3D::RGB10_A2: |
| 601 | case GraphicsContext3D::RGBA16F: |
| 602 | case GraphicsContext3D::RGBA32F: |
| 603 | case GraphicsContext3D::RGBA8UI: |
| 604 | case GraphicsContext3D::RGBA8I: |
| 605 | case GraphicsContext3D::RGB10_A2UI: |
| 606 | case GraphicsContext3D::RGBA16UI: |
| 607 | case GraphicsContext3D::RGBA16I: |
| 608 | case GraphicsContext3D::RGBA32I: |
| 609 | case GraphicsContext3D::RGBA32UI: |
| 610 | case Extensions3D::SRGB_EXT: |
| 611 | case Extensions3D::SRGB_ALPHA_EXT: |
| 612 | return GraphicsContext3D::COLOR_BUFFER_BIT; |
| 613 | case GraphicsContext3D::DEPTH_COMPONENT16: |
| 614 | case GraphicsContext3D::DEPTH_COMPONENT24: |
| 615 | case GraphicsContext3D::DEPTH_COMPONENT32F: |
| 616 | case GraphicsContext3D::DEPTH_COMPONENT: |
| 617 | return GraphicsContext3D::DEPTH_BUFFER_BIT; |
| 618 | case GraphicsContext3D::STENCIL_INDEX8: |
| 619 | return GraphicsContext3D::STENCIL_BUFFER_BIT; |
| 620 | case GraphicsContext3D::DEPTH_STENCIL: |
| 621 | case GraphicsContext3D::DEPTH24_STENCIL8: |
| 622 | case GraphicsContext3D::DEPTH32F_STENCIL8: |
| 623 | return GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT; |
| 624 | default: |
| 625 | return 0; |
| 626 | } |
| 627 | } |
| 628 | |
| 629 | unsigned GraphicsContext3D::getChannelBitsByFormat(GC3Denum format) |
| 630 | { |
| 631 | switch (format) { |
| 632 | case GraphicsContext3D::ALPHA: |
| 633 | return ChannelAlpha; |
| 634 | case GraphicsContext3D::LUMINANCE: |
| 635 | return ChannelRGB; |
| 636 | case GraphicsContext3D::LUMINANCE_ALPHA: |
| 637 | return ChannelRGBA; |
| 638 | case GraphicsContext3D::RGB: |
| 639 | case GraphicsContext3D::RGB565: |
| 640 | case Extensions3D::SRGB_EXT: |
| 641 | return ChannelRGB; |
| 642 | case GraphicsContext3D::RGBA: |
| 643 | case GraphicsContext3D::RGBA4: |
| 644 | case GraphicsContext3D::RGB5_A1: |
| 645 | case Extensions3D::SRGB_ALPHA_EXT: |
| 646 | return ChannelRGBA; |
| 647 | case GraphicsContext3D::DEPTH_COMPONENT16: |
| 648 | case GraphicsContext3D::DEPTH_COMPONENT: |
| 649 | return ChannelDepth; |
| 650 | case GraphicsContext3D::STENCIL_INDEX8: |
| 651 | return ChannelStencil; |
| 652 | case GraphicsContext3D::DEPTH_STENCIL: |
| 653 | return ChannelDepth | ChannelStencil; |
| 654 | default: |
| 655 | return 0; |
| 656 | } |
| 657 | } |
| 658 | |
| 659 | #if !(PLATFORM(COCOA) && USE(OPENGL)) |
| 660 | void GraphicsContext3D::setContextVisibility(bool) |
| 661 | { |
| 662 | } |
| 663 | #endif |
| 664 | |
| 665 | #if !PLATFORM(COCOA) |
| 666 | void GraphicsContext3D::simulateContextChanged() |
| 667 | { |
| 668 | } |
| 669 | #endif |
| 670 | |
| 671 | } // namespace WebCore |
| 672 | |
| 673 | #endif // ENABLE(GRAPHICS_CONTEXT_3D) |
| 674 | |