Coverage Report

Created: 2018-09-25 14:53

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