gfx/gl/GLUploadHelpers.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "GLUploadHelpers.h"
michael@0 7
michael@0 8 #include "GLContext.h"
michael@0 9 #include "mozilla/gfx/2D.h"
michael@0 10 #include "mozilla/gfx/Tools.h" // For BytesPerPixel
michael@0 11 #include "nsRegion.h"
michael@0 12
michael@0 13 namespace mozilla {
michael@0 14
michael@0 15 using namespace gfx;
michael@0 16
michael@0 17 namespace gl {
michael@0 18
michael@0 19 /* These two techniques are suggested by "Bit Twiddling Hacks"
michael@0 20 */
michael@0 21
michael@0 22 /**
michael@0 23 * Returns true if |aNumber| is a power of two
michael@0 24 * 0 is incorreclty considered a power of two
michael@0 25 */
michael@0 26 static bool
michael@0 27 IsPowerOfTwo(int aNumber)
michael@0 28 {
michael@0 29 return (aNumber & (aNumber - 1)) == 0;
michael@0 30 }
michael@0 31
michael@0 32 /**
michael@0 33 * Returns the first integer greater than |aNumber| which is a power of two
michael@0 34 * Undefined for |aNumber| < 0
michael@0 35 */
michael@0 36 static int
michael@0 37 NextPowerOfTwo(int aNumber)
michael@0 38 {
michael@0 39 #if defined(__arm__)
michael@0 40 return 1 << (32 - __builtin_clz(aNumber - 1));
michael@0 41 #else
michael@0 42 --aNumber;
michael@0 43 aNumber |= aNumber >> 1;
michael@0 44 aNumber |= aNumber >> 2;
michael@0 45 aNumber |= aNumber >> 4;
michael@0 46 aNumber |= aNumber >> 8;
michael@0 47 aNumber |= aNumber >> 16;
michael@0 48 return ++aNumber;
michael@0 49 #endif
michael@0 50 }
michael@0 51
michael@0 52 static unsigned int
michael@0 53 DataOffset(const nsIntPoint &aPoint, int32_t aStride, SurfaceFormat aFormat)
michael@0 54 {
michael@0 55 unsigned int data = aPoint.y * aStride;
michael@0 56 data += aPoint.x * BytesPerPixel(aFormat);
michael@0 57 return data;
michael@0 58 }
michael@0 59
michael@0 60 static GLint GetAddressAlignment(ptrdiff_t aAddress)
michael@0 61 {
michael@0 62 if (!(aAddress & 0x7)) {
michael@0 63 return 8;
michael@0 64 } else if (!(aAddress & 0x3)) {
michael@0 65 return 4;
michael@0 66 } else if (!(aAddress & 0x1)) {
michael@0 67 return 2;
michael@0 68 } else {
michael@0 69 return 1;
michael@0 70 }
michael@0 71 }
michael@0 72
michael@0 73 // Take texture data in a given buffer and copy it into a larger buffer,
michael@0 74 // padding out the edge pixels for filtering if necessary
michael@0 75 static void
michael@0 76 CopyAndPadTextureData(const GLvoid* srcBuffer,
michael@0 77 GLvoid* dstBuffer,
michael@0 78 GLsizei srcWidth, GLsizei srcHeight,
michael@0 79 GLsizei dstWidth, GLsizei dstHeight,
michael@0 80 GLsizei stride, GLint pixelsize)
michael@0 81 {
michael@0 82 unsigned char *rowDest = static_cast<unsigned char*>(dstBuffer);
michael@0 83 const unsigned char *source = static_cast<const unsigned char*>(srcBuffer);
michael@0 84
michael@0 85 for (GLsizei h = 0; h < srcHeight; ++h) {
michael@0 86 memcpy(rowDest, source, srcWidth * pixelsize);
michael@0 87 rowDest += dstWidth * pixelsize;
michael@0 88 source += stride;
michael@0 89 }
michael@0 90
michael@0 91 GLsizei padHeight = srcHeight;
michael@0 92
michael@0 93 // Pad out an extra row of pixels so that edge filtering doesn't use garbage data
michael@0 94 if (dstHeight > srcHeight) {
michael@0 95 memcpy(rowDest, source - stride, srcWidth * pixelsize);
michael@0 96 padHeight++;
michael@0 97 }
michael@0 98
michael@0 99 // Pad out an extra column of pixels
michael@0 100 if (dstWidth > srcWidth) {
michael@0 101 rowDest = static_cast<unsigned char*>(dstBuffer) + srcWidth * pixelsize;
michael@0 102 for (GLsizei h = 0; h < padHeight; ++h) {
michael@0 103 memcpy(rowDest, rowDest - pixelsize, pixelsize);
michael@0 104 rowDest += dstWidth * pixelsize;
michael@0 105 }
michael@0 106 }
michael@0 107 }
michael@0 108
michael@0 109 // In both of these cases (for the Adreno at least) it is impossible
michael@0 110 // to determine good or bad driver versions for POT texture uploads,
michael@0 111 // so blacklist them all. Newer drivers use a different rendering
michael@0 112 // string in the form "Adreno (TM) 200" and the drivers we've seen so
michael@0 113 // far work fine with NPOT textures, so don't blacklist those until we
michael@0 114 // have evidence of any problems with them.
michael@0 115 bool
michael@0 116 CanUploadSubTextures(GLContext* gl)
michael@0 117 {
michael@0 118 if (!gl->WorkAroundDriverBugs())
michael@0 119 return true;
michael@0 120
michael@0 121 // There are certain GPUs that we don't want to use glTexSubImage2D on
michael@0 122 // because that function can be very slow and/or buggy
michael@0 123 if (gl->Renderer() == GLRenderer::Adreno200 ||
michael@0 124 gl->Renderer() == GLRenderer::Adreno205)
michael@0 125 {
michael@0 126 return false;
michael@0 127 }
michael@0 128
michael@0 129 // On PowerVR glTexSubImage does a readback, so it will be slower
michael@0 130 // than just doing a glTexImage2D() directly. i.e. 26ms vs 10ms
michael@0 131 if (gl->Renderer() == GLRenderer::SGX540 ||
michael@0 132 gl->Renderer() == GLRenderer::SGX530)
michael@0 133 {
michael@0 134 return false;
michael@0 135 }
michael@0 136
michael@0 137 return true;
michael@0 138 }
michael@0 139
michael@0 140 static void
michael@0 141 TexSubImage2DWithUnpackSubimageGLES(GLContext* gl,
michael@0 142 GLenum target, GLint level,
michael@0 143 GLint xoffset, GLint yoffset,
michael@0 144 GLsizei width, GLsizei height,
michael@0 145 GLsizei stride, GLint pixelsize,
michael@0 146 GLenum format, GLenum type,
michael@0 147 const GLvoid* pixels)
michael@0 148 {
michael@0 149 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
michael@0 150 std::min(GetAddressAlignment((ptrdiff_t)pixels),
michael@0 151 GetAddressAlignment((ptrdiff_t)stride)));
michael@0 152 // When using GL_UNPACK_ROW_LENGTH, we need to work around a Tegra
michael@0 153 // driver crash where the driver apparently tries to read
michael@0 154 // (stride - width * pixelsize) bytes past the end of the last input
michael@0 155 // row. We only upload the first height-1 rows using GL_UNPACK_ROW_LENGTH,
michael@0 156 // and then we upload the final row separately. See bug 697990.
michael@0 157 int rowLength = stride/pixelsize;
michael@0 158 gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
michael@0 159 gl->fTexSubImage2D(target,
michael@0 160 level,
michael@0 161 xoffset,
michael@0 162 yoffset,
michael@0 163 width,
michael@0 164 height-1,
michael@0 165 format,
michael@0 166 type,
michael@0 167 pixels);
michael@0 168 gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
michael@0 169 gl->fTexSubImage2D(target,
michael@0 170 level,
michael@0 171 xoffset,
michael@0 172 yoffset+height-1,
michael@0 173 width,
michael@0 174 1,
michael@0 175 format,
michael@0 176 type,
michael@0 177 (const unsigned char *)pixels+(height-1)*stride);
michael@0 178 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
michael@0 179 }
michael@0 180
michael@0 181 static void
michael@0 182 TexSubImage2DWithoutUnpackSubimage(GLContext* gl,
michael@0 183 GLenum target, GLint level,
michael@0 184 GLint xoffset, GLint yoffset,
michael@0 185 GLsizei width, GLsizei height,
michael@0 186 GLsizei stride, GLint pixelsize,
michael@0 187 GLenum format, GLenum type,
michael@0 188 const GLvoid* pixels)
michael@0 189 {
michael@0 190 // Not using the whole row of texture data and GL_UNPACK_ROW_LENGTH
michael@0 191 // isn't supported. We make a copy of the texture data we're using,
michael@0 192 // such that we're using the whole row of data in the copy. This turns
michael@0 193 // out to be more efficient than uploading row-by-row; see bug 698197.
michael@0 194 unsigned char *newPixels = new unsigned char[width*height*pixelsize];
michael@0 195 unsigned char *rowDest = newPixels;
michael@0 196 const unsigned char *rowSource = (const unsigned char *)pixels;
michael@0 197 for (int h = 0; h < height; h++) {
michael@0 198 memcpy(rowDest, rowSource, width*pixelsize);
michael@0 199 rowDest += width*pixelsize;
michael@0 200 rowSource += stride;
michael@0 201 }
michael@0 202
michael@0 203 stride = width*pixelsize;
michael@0 204 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
michael@0 205 std::min(GetAddressAlignment((ptrdiff_t)newPixels),
michael@0 206 GetAddressAlignment((ptrdiff_t)stride)));
michael@0 207 gl->fTexSubImage2D(target,
michael@0 208 level,
michael@0 209 xoffset,
michael@0 210 yoffset,
michael@0 211 width,
michael@0 212 height,
michael@0 213 format,
michael@0 214 type,
michael@0 215 newPixels);
michael@0 216 delete [] newPixels;
michael@0 217 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
michael@0 218 }
michael@0 219
michael@0 220 static void
michael@0 221 TexSubImage2DHelper(GLContext *gl,
michael@0 222 GLenum target, GLint level,
michael@0 223 GLint xoffset, GLint yoffset,
michael@0 224 GLsizei width, GLsizei height, GLsizei stride,
michael@0 225 GLint pixelsize, GLenum format,
michael@0 226 GLenum type, const GLvoid* pixels)
michael@0 227 {
michael@0 228 if (gl->IsGLES()) {
michael@0 229 if (stride == width * pixelsize) {
michael@0 230 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
michael@0 231 std::min(GetAddressAlignment((ptrdiff_t)pixels),
michael@0 232 GetAddressAlignment((ptrdiff_t)stride)));
michael@0 233 gl->fTexSubImage2D(target,
michael@0 234 level,
michael@0 235 xoffset,
michael@0 236 yoffset,
michael@0 237 width,
michael@0 238 height,
michael@0 239 format,
michael@0 240 type,
michael@0 241 pixels);
michael@0 242 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
michael@0 243 } else if (gl->IsExtensionSupported(GLContext::EXT_unpack_subimage)) {
michael@0 244 TexSubImage2DWithUnpackSubimageGLES(gl, target, level, xoffset, yoffset,
michael@0 245 width, height, stride,
michael@0 246 pixelsize, format, type, pixels);
michael@0 247
michael@0 248 } else {
michael@0 249 TexSubImage2DWithoutUnpackSubimage(gl, target, level, xoffset, yoffset,
michael@0 250 width, height, stride,
michael@0 251 pixelsize, format, type, pixels);
michael@0 252 }
michael@0 253 } else {
michael@0 254 // desktop GL (non-ES) path
michael@0 255 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
michael@0 256 std::min(GetAddressAlignment((ptrdiff_t)pixels),
michael@0 257 GetAddressAlignment((ptrdiff_t)stride)));
michael@0 258 int rowLength = stride/pixelsize;
michael@0 259 gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
michael@0 260 gl->fTexSubImage2D(target,
michael@0 261 level,
michael@0 262 xoffset,
michael@0 263 yoffset,
michael@0 264 width,
michael@0 265 height,
michael@0 266 format,
michael@0 267 type,
michael@0 268 pixels);
michael@0 269 gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
michael@0 270 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
michael@0 271 }
michael@0 272 }
michael@0 273
michael@0 274 static void
michael@0 275 TexImage2DHelper(GLContext *gl,
michael@0 276 GLenum target, GLint level, GLint internalformat,
michael@0 277 GLsizei width, GLsizei height, GLsizei stride,
michael@0 278 GLint pixelsize, GLint border, GLenum format,
michael@0 279 GLenum type, const GLvoid *pixels)
michael@0 280 {
michael@0 281 if (gl->IsGLES()) {
michael@0 282
michael@0 283 NS_ASSERTION(format == (GLenum)internalformat,
michael@0 284 "format and internalformat not the same for glTexImage2D on GLES2");
michael@0 285
michael@0 286 if (!CanUploadNonPowerOfTwo(gl)
michael@0 287 && (stride != width * pixelsize
michael@0 288 || !IsPowerOfTwo(width)
michael@0 289 || !IsPowerOfTwo(height))) {
michael@0 290
michael@0 291 // Pad out texture width and height to the next power of two
michael@0 292 // as we don't support/want non power of two texture uploads
michael@0 293 GLsizei paddedWidth = NextPowerOfTwo(width);
michael@0 294 GLsizei paddedHeight = NextPowerOfTwo(height);
michael@0 295
michael@0 296 GLvoid* paddedPixels = new unsigned char[paddedWidth * paddedHeight * pixelsize];
michael@0 297
michael@0 298 // Pad out texture data to be in a POT sized buffer for uploading to
michael@0 299 // a POT sized texture
michael@0 300 CopyAndPadTextureData(pixels, paddedPixels, width, height,
michael@0 301 paddedWidth, paddedHeight, stride, pixelsize);
michael@0 302
michael@0 303 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
michael@0 304 std::min(GetAddressAlignment((ptrdiff_t)paddedPixels),
michael@0 305 GetAddressAlignment((ptrdiff_t)paddedWidth * pixelsize)));
michael@0 306 gl->fTexImage2D(target,
michael@0 307 border,
michael@0 308 internalformat,
michael@0 309 paddedWidth,
michael@0 310 paddedHeight,
michael@0 311 border,
michael@0 312 format,
michael@0 313 type,
michael@0 314 paddedPixels);
michael@0 315 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
michael@0 316
michael@0 317 delete[] static_cast<unsigned char*>(paddedPixels);
michael@0 318 return;
michael@0 319 }
michael@0 320
michael@0 321 if (stride == width * pixelsize) {
michael@0 322 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
michael@0 323 std::min(GetAddressAlignment((ptrdiff_t)pixels),
michael@0 324 GetAddressAlignment((ptrdiff_t)stride)));
michael@0 325 gl->fTexImage2D(target,
michael@0 326 border,
michael@0 327 internalformat,
michael@0 328 width,
michael@0 329 height,
michael@0 330 border,
michael@0 331 format,
michael@0 332 type,
michael@0 333 pixels);
michael@0 334 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
michael@0 335 } else {
michael@0 336 // Use GLES-specific workarounds for GL_UNPACK_ROW_LENGTH; these are
michael@0 337 // implemented in TexSubImage2D.
michael@0 338 gl->fTexImage2D(target,
michael@0 339 border,
michael@0 340 internalformat,
michael@0 341 width,
michael@0 342 height,
michael@0 343 border,
michael@0 344 format,
michael@0 345 type,
michael@0 346 nullptr);
michael@0 347 TexSubImage2DHelper(gl,
michael@0 348 target,
michael@0 349 level,
michael@0 350 0,
michael@0 351 0,
michael@0 352 width,
michael@0 353 height,
michael@0 354 stride,
michael@0 355 pixelsize,
michael@0 356 format,
michael@0 357 type,
michael@0 358 pixels);
michael@0 359 }
michael@0 360 } else {
michael@0 361 // desktop GL (non-ES) path
michael@0 362
michael@0 363 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
michael@0 364 std::min(GetAddressAlignment((ptrdiff_t)pixels),
michael@0 365 GetAddressAlignment((ptrdiff_t)stride)));
michael@0 366 int rowLength = stride/pixelsize;
michael@0 367 gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
michael@0 368 gl->fTexImage2D(target,
michael@0 369 level,
michael@0 370 internalformat,
michael@0 371 width,
michael@0 372 height,
michael@0 373 border,
michael@0 374 format,
michael@0 375 type,
michael@0 376 pixels);
michael@0 377 gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
michael@0 378 gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
michael@0 379 }
michael@0 380 }
michael@0 381
michael@0 382 SurfaceFormat
michael@0 383 UploadImageDataToTexture(GLContext* gl,
michael@0 384 unsigned char* aData,
michael@0 385 int32_t aStride,
michael@0 386 SurfaceFormat aFormat,
michael@0 387 const nsIntRegion& aDstRegion,
michael@0 388 GLuint& aTexture,
michael@0 389 bool aOverwrite,
michael@0 390 bool aPixelBuffer,
michael@0 391 GLenum aTextureUnit,
michael@0 392 GLenum aTextureTarget)
michael@0 393 {
michael@0 394 bool textureInited = aOverwrite ? false : true;
michael@0 395 gl->MakeCurrent();
michael@0 396 gl->fActiveTexture(aTextureUnit);
michael@0 397
michael@0 398 if (!aTexture) {
michael@0 399 gl->fGenTextures(1, &aTexture);
michael@0 400 gl->fBindTexture(aTextureTarget, aTexture);
michael@0 401 gl->fTexParameteri(aTextureTarget,
michael@0 402 LOCAL_GL_TEXTURE_MIN_FILTER,
michael@0 403 LOCAL_GL_LINEAR);
michael@0 404 gl->fTexParameteri(aTextureTarget,
michael@0 405 LOCAL_GL_TEXTURE_MAG_FILTER,
michael@0 406 LOCAL_GL_LINEAR);
michael@0 407 gl->fTexParameteri(aTextureTarget,
michael@0 408 LOCAL_GL_TEXTURE_WRAP_S,
michael@0 409 LOCAL_GL_CLAMP_TO_EDGE);
michael@0 410 gl->fTexParameteri(aTextureTarget,
michael@0 411 LOCAL_GL_TEXTURE_WRAP_T,
michael@0 412 LOCAL_GL_CLAMP_TO_EDGE);
michael@0 413 textureInited = false;
michael@0 414 } else {
michael@0 415 gl->fBindTexture(aTextureTarget, aTexture);
michael@0 416 }
michael@0 417
michael@0 418 nsIntRegion paintRegion;
michael@0 419 if (!textureInited) {
michael@0 420 paintRegion = nsIntRegion(aDstRegion.GetBounds());
michael@0 421 } else {
michael@0 422 paintRegion = aDstRegion;
michael@0 423 }
michael@0 424
michael@0 425 GLenum format = 0;
michael@0 426 GLenum internalFormat = 0;
michael@0 427 GLenum type = 0;
michael@0 428 int32_t pixelSize = BytesPerPixel(aFormat);
michael@0 429 SurfaceFormat surfaceFormat = gfx::SurfaceFormat::UNKNOWN;
michael@0 430
michael@0 431 MOZ_ASSERT(gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
michael@0 432 gl->GetPreferredARGB32Format() == LOCAL_GL_RGBA);
michael@0 433 switch (aFormat) {
michael@0 434 case SurfaceFormat::B8G8R8A8:
michael@0 435 if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
michael@0 436 format = LOCAL_GL_BGRA;
michael@0 437 surfaceFormat = SurfaceFormat::R8G8B8A8;
michael@0 438 type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
michael@0 439 } else {
michael@0 440 format = LOCAL_GL_RGBA;
michael@0 441 surfaceFormat = SurfaceFormat::B8G8R8A8;
michael@0 442 type = LOCAL_GL_UNSIGNED_BYTE;
michael@0 443 }
michael@0 444 internalFormat = LOCAL_GL_RGBA;
michael@0 445 break;
michael@0 446 case SurfaceFormat::B8G8R8X8:
michael@0 447 // Treat BGRX surfaces as BGRA except for the surface
michael@0 448 // format used.
michael@0 449 if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
michael@0 450 format = LOCAL_GL_BGRA;
michael@0 451 surfaceFormat = SurfaceFormat::R8G8B8X8;
michael@0 452 type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
michael@0 453 } else {
michael@0 454 format = LOCAL_GL_RGBA;
michael@0 455 surfaceFormat = SurfaceFormat::B8G8R8X8;
michael@0 456 type = LOCAL_GL_UNSIGNED_BYTE;
michael@0 457 }
michael@0 458 internalFormat = LOCAL_GL_RGBA;
michael@0 459 break;
michael@0 460 case SurfaceFormat::R5G6B5:
michael@0 461 internalFormat = format = LOCAL_GL_RGB;
michael@0 462 type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
michael@0 463 surfaceFormat = SurfaceFormat::R5G6B5;
michael@0 464 break;
michael@0 465 case SurfaceFormat::A8:
michael@0 466 internalFormat = format = LOCAL_GL_LUMINANCE;
michael@0 467 type = LOCAL_GL_UNSIGNED_BYTE;
michael@0 468 // We don't have a specific luminance shader
michael@0 469 surfaceFormat = SurfaceFormat::A8;
michael@0 470 break;
michael@0 471 default:
michael@0 472 NS_ASSERTION(false, "Unhandled image surface format!");
michael@0 473 }
michael@0 474
michael@0 475 nsIntRegionRectIterator iter(paintRegion);
michael@0 476 const nsIntRect *iterRect;
michael@0 477
michael@0 478 // Top left point of the region's bounding rectangle.
michael@0 479 nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
michael@0 480
michael@0 481 while ((iterRect = iter.Next())) {
michael@0 482 // The inital data pointer is at the top left point of the region's
michael@0 483 // bounding rectangle. We need to find the offset of this rect
michael@0 484 // within the region and adjust the data pointer accordingly.
michael@0 485 unsigned char *rectData =
michael@0 486 aData + DataOffset(iterRect->TopLeft() - topLeft, aStride, aFormat);
michael@0 487
michael@0 488 NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
michael@0 489 "Must be uploading to the origin when we don't have an existing texture");
michael@0 490
michael@0 491 if (textureInited && CanUploadSubTextures(gl)) {
michael@0 492 TexSubImage2DHelper(gl,
michael@0 493 aTextureTarget,
michael@0 494 0,
michael@0 495 iterRect->x,
michael@0 496 iterRect->y,
michael@0 497 iterRect->width,
michael@0 498 iterRect->height,
michael@0 499 aStride,
michael@0 500 pixelSize,
michael@0 501 format,
michael@0 502 type,
michael@0 503 rectData);
michael@0 504 } else {
michael@0 505 TexImage2DHelper(gl,
michael@0 506 aTextureTarget,
michael@0 507 0,
michael@0 508 internalFormat,
michael@0 509 iterRect->width,
michael@0 510 iterRect->height,
michael@0 511 aStride,
michael@0 512 pixelSize,
michael@0 513 0,
michael@0 514 format,
michael@0 515 type,
michael@0 516 rectData);
michael@0 517 }
michael@0 518
michael@0 519 }
michael@0 520
michael@0 521 return surfaceFormat;
michael@0 522 }
michael@0 523
michael@0 524 SurfaceFormat
michael@0 525 UploadSurfaceToTexture(GLContext* gl,
michael@0 526 DataSourceSurface *aSurface,
michael@0 527 const nsIntRegion& aDstRegion,
michael@0 528 GLuint& aTexture,
michael@0 529 bool aOverwrite,
michael@0 530 const nsIntPoint& aSrcPoint,
michael@0 531 bool aPixelBuffer,
michael@0 532 GLenum aTextureUnit,
michael@0 533 GLenum aTextureTarget)
michael@0 534 {
michael@0 535 unsigned char* data = aPixelBuffer ? nullptr : aSurface->GetData();
michael@0 536 int32_t stride = aSurface->Stride();
michael@0 537 SurfaceFormat format = aSurface->GetFormat();
michael@0 538 data += DataOffset(aSrcPoint, stride, format);
michael@0 539 return UploadImageDataToTexture(gl, data, stride, format,
michael@0 540 aDstRegion, aTexture, aOverwrite,
michael@0 541 aPixelBuffer, aTextureUnit,
michael@0 542 aTextureTarget);
michael@0 543 }
michael@0 544
michael@0 545 bool
michael@0 546 CanUploadNonPowerOfTwo(GLContext* gl)
michael@0 547 {
michael@0 548 if (!gl->WorkAroundDriverBugs())
michael@0 549 return true;
michael@0 550
michael@0 551 // Some GPUs driver crash when uploading non power of two 565 textures.
michael@0 552 return gl->Renderer() != GLRenderer::Adreno200 &&
michael@0 553 gl->Renderer() != GLRenderer::Adreno205;
michael@0 554 }
michael@0 555
michael@0 556 }
michael@0 557 }

mercurial