1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "MacIOSurface.h"
9 #include <OpenGL/CGLIOSurface.h>
10 #include <QuartzCore/QuartzCore.h>
12 #include "GLContextCGL.h"
13 #include "nsPrintfCString.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/RefPtr.h"
16 #include "mozilla/gfx/Logging.h"
17 #include "mozilla/StaticPrefs_gfx.h"
19 using namespace mozilla
;
21 MacIOSurface::MacIOSurface(CFTypeRefPtr
<IOSurfaceRef
> aIOSurfaceRef
,
22 bool aHasAlpha
, gfx::YUVColorSpace aColorSpace
)
23 : mIOSurfaceRef(std::move(aIOSurfaceRef
)),
25 mColorSpace(aColorSpace
) {
29 MacIOSurface::~MacIOSurface() {
30 MOZ_RELEASE_ASSERT(!IsLocked(), "Destroying locked surface");
34 void AddDictionaryInt(const CFTypeRefPtr
<CFMutableDictionaryRef
>& aDict
,
35 const void* aType
, uint32_t aValue
) {
36 auto cfValue
= CFTypeRefPtr
<CFNumberRef
>::WrapUnderCreateRule(
37 ::CFNumberCreate(nullptr, kCFNumberSInt32Type
, &aValue
));
38 ::CFDictionaryAddValue(aDict
.get(), aType
, cfValue
.get());
41 void SetSizeProperties(const CFTypeRefPtr
<CFMutableDictionaryRef
>& aDict
,
42 int aWidth
, int aHeight
, int aBytesPerPixel
) {
43 AddDictionaryInt(aDict
, kIOSurfaceWidth
, aWidth
);
44 AddDictionaryInt(aDict
, kIOSurfaceHeight
, aHeight
);
45 ::CFDictionaryAddValue(aDict
.get(), kIOSurfaceIsGlobal
, kCFBooleanTrue
);
46 AddDictionaryInt(aDict
, kIOSurfaceBytesPerElement
, aBytesPerPixel
);
49 IOSurfaceAlignProperty(kIOSurfaceBytesPerRow
, aWidth
* aBytesPerPixel
);
50 AddDictionaryInt(aDict
, kIOSurfaceBytesPerRow
, bytesPerRow
);
52 // Add a SIMD register worth of extra bytes to the end of the allocation for
55 IOSurfaceAlignProperty(kIOSurfaceAllocSize
, aHeight
* bytesPerRow
+ 16);
56 AddDictionaryInt(aDict
, kIOSurfaceAllocSize
, totalBytes
);
60 already_AddRefed
<MacIOSurface
> MacIOSurface::CreateIOSurface(int aWidth
,
63 auto props
= CFTypeRefPtr
<CFMutableDictionaryRef
>::WrapUnderCreateRule(
64 ::CFDictionaryCreateMutable(kCFAllocatorDefault
, 4,
65 &kCFTypeDictionaryKeyCallBacks
,
66 &kCFTypeDictionaryValueCallBacks
));
67 if (!props
) return nullptr;
69 MOZ_ASSERT((size_t)aWidth
<= GetMaxWidth());
70 MOZ_ASSERT((size_t)aHeight
<= GetMaxHeight());
72 int32_t bytesPerElem
= 4;
73 SetSizeProperties(props
, aWidth
, aHeight
, bytesPerElem
);
75 AddDictionaryInt(props
, kIOSurfacePixelFormat
,
76 (uint32_t)kCVPixelFormatType_32BGRA
);
78 CFTypeRefPtr
<IOSurfaceRef
> surfaceRef
=
79 CFTypeRefPtr
<IOSurfaceRef
>::WrapUnderCreateRule(
80 ::IOSurfaceCreate(props
.get()));
82 if (StaticPrefs::gfx_color_management_native_srgb()) {
83 IOSurfaceSetValue(surfaceRef
.get(), CFSTR("IOSurfaceColorSpace"),
91 RefPtr
<MacIOSurface
> ioSurface
=
92 new MacIOSurface(std::move(surfaceRef
), aHasAlpha
);
94 return ioSurface
.forget();
97 size_t CreatePlaneDictionary(CFTypeRefPtr
<CFMutableDictionaryRef
>& aDict
,
98 const gfx::IntSize
& aSize
, size_t aOffset
,
99 size_t aBytesPerPixel
) {
100 size_t bytesPerRow
= IOSurfaceAlignProperty(kIOSurfaceBytesPerRow
,
101 aSize
.width
* aBytesPerPixel
);
102 // Add a SIMD register worth of extra bytes to the end of the allocation for
104 size_t totalBytes
= IOSurfaceAlignProperty(kIOSurfaceAllocSize
,
105 aSize
.height
* bytesPerRow
+ 16);
107 aDict
= CFTypeRefPtr
<CFMutableDictionaryRef
>::WrapUnderCreateRule(
108 ::CFDictionaryCreateMutable(kCFAllocatorDefault
, 4,
109 &kCFTypeDictionaryKeyCallBacks
,
110 &kCFTypeDictionaryValueCallBacks
));
112 AddDictionaryInt(aDict
, kIOSurfacePlaneWidth
, aSize
.width
);
113 AddDictionaryInt(aDict
, kIOSurfacePlaneHeight
, aSize
.height
);
114 AddDictionaryInt(aDict
, kIOSurfacePlaneBytesPerRow
, bytesPerRow
);
115 AddDictionaryInt(aDict
, kIOSurfacePlaneOffset
, aOffset
);
116 AddDictionaryInt(aDict
, kIOSurfacePlaneSize
, totalBytes
);
117 AddDictionaryInt(aDict
, kIOSurfaceBytesPerElement
, aBytesPerPixel
);
123 already_AddRefed
<MacIOSurface
> MacIOSurface::CreateNV12Surface(
124 const IntSize
& aYSize
, const IntSize
& aCbCrSize
, YUVColorSpace aColorSpace
,
125 ColorRange aColorRange
) {
126 MOZ_ASSERT(aColorSpace
== YUVColorSpace::BT601
||
127 aColorSpace
== YUVColorSpace::BT709
);
128 MOZ_ASSERT(aColorRange
== ColorRange::LIMITED
||
129 aColorRange
== ColorRange::FULL
);
131 auto props
= CFTypeRefPtr
<CFMutableDictionaryRef
>::WrapUnderCreateRule(
132 ::CFDictionaryCreateMutable(kCFAllocatorDefault
, 4,
133 &kCFTypeDictionaryKeyCallBacks
,
134 &kCFTypeDictionaryValueCallBacks
));
135 if (!props
) return nullptr;
137 MOZ_ASSERT((size_t)aYSize
.width
<= GetMaxWidth());
138 MOZ_ASSERT((size_t)aYSize
.height
<= GetMaxHeight());
140 AddDictionaryInt(props
, kIOSurfaceWidth
, aYSize
.width
);
141 AddDictionaryInt(props
, kIOSurfaceHeight
, aYSize
.height
);
142 ::CFDictionaryAddValue(props
.get(), kIOSurfaceIsGlobal
, kCFBooleanTrue
);
144 if (aColorRange
== ColorRange::LIMITED
) {
145 AddDictionaryInt(props
, kIOSurfacePixelFormat
,
146 (uint32_t)kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
);
148 AddDictionaryInt(props
, kIOSurfacePixelFormat
,
149 (uint32_t)kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
);
152 CFTypeRefPtr
<CFMutableDictionaryRef
> planeProps
[2];
153 size_t planeTotalBytes
= CreatePlaneDictionary(planeProps
[0], aYSize
, 0, 1);
155 CreatePlaneDictionary(planeProps
[1], aCbCrSize
, planeTotalBytes
, 2);
157 AddDictionaryInt(props
, kIOSurfaceAllocSize
, planeTotalBytes
);
159 auto array
= CFTypeRefPtr
<CFArrayRef
>::WrapUnderCreateRule(
160 CFArrayCreate(kCFAllocatorDefault
, (const void**)planeProps
, 2,
161 &kCFTypeArrayCallBacks
));
162 ::CFDictionaryAddValue(props
.get(), kIOSurfacePlaneInfo
, array
.get());
164 CFTypeRefPtr
<IOSurfaceRef
> surfaceRef
=
165 CFTypeRefPtr
<IOSurfaceRef
>::WrapUnderCreateRule(
166 ::IOSurfaceCreate(props
.get()));
172 // Setup the correct YCbCr conversion matrix on the IOSurface, in case we pass
173 // this directly to CoreAnimation.
174 if (aColorSpace
== YUVColorSpace::BT601
) {
175 IOSurfaceSetValue(surfaceRef
.get(), CFSTR("IOSurfaceYCbCrMatrix"),
176 CFSTR("ITU_R_601_4"));
178 IOSurfaceSetValue(surfaceRef
.get(), CFSTR("IOSurfaceYCbCrMatrix"),
179 CFSTR("ITU_R_709_2"));
181 // Override the color space to be the same as the main display, so that
182 // CoreAnimation won't try to do any color correction (from the IOSurface
183 // space, to the display). In the future we may want to try specifying this
184 // correctly, but probably only once we do the same for videos drawn through
186 auto colorSpace
= CFTypeRefPtr
<CGColorSpaceRef
>::WrapUnderCreateRule(
187 CGDisplayCopyColorSpace(CGMainDisplayID()));
188 auto colorData
= CFTypeRefPtr
<CFDataRef
>::WrapUnderCreateRule(
189 CGColorSpaceCopyICCProfile(colorSpace
.get()));
190 IOSurfaceSetValue(surfaceRef
.get(), CFSTR("IOSurfaceColorSpace"),
193 RefPtr
<MacIOSurface
> ioSurface
=
194 new MacIOSurface(std::move(surfaceRef
), false, aColorSpace
);
196 return ioSurface
.forget();
200 already_AddRefed
<MacIOSurface
> MacIOSurface::CreateYUV422Surface(
201 const IntSize
& aSize
, YUVColorSpace aColorSpace
, ColorRange aColorRange
) {
202 MOZ_ASSERT(aColorSpace
== YUVColorSpace::BT601
||
203 aColorSpace
== YUVColorSpace::BT709
);
204 MOZ_ASSERT(aColorRange
== ColorRange::LIMITED
||
205 aColorRange
== ColorRange::FULL
);
207 auto props
= CFTypeRefPtr
<CFMutableDictionaryRef
>::WrapUnderCreateRule(
208 ::CFDictionaryCreateMutable(kCFAllocatorDefault
, 4,
209 &kCFTypeDictionaryKeyCallBacks
,
210 &kCFTypeDictionaryValueCallBacks
));
211 if (!props
) return nullptr;
213 MOZ_ASSERT((size_t)aSize
.width
<= GetMaxWidth());
214 MOZ_ASSERT((size_t)aSize
.height
<= GetMaxHeight());
216 SetSizeProperties(props
, aSize
.width
, aSize
.height
, 2);
218 if (aColorRange
== ColorRange::LIMITED
) {
219 AddDictionaryInt(props
, kIOSurfacePixelFormat
,
220 (uint32_t)kCVPixelFormatType_422YpCbCr8_yuvs
);
222 AddDictionaryInt(props
, kIOSurfacePixelFormat
,
223 (uint32_t)kCVPixelFormatType_422YpCbCr8FullRange
);
226 CFTypeRefPtr
<IOSurfaceRef
> surfaceRef
=
227 CFTypeRefPtr
<IOSurfaceRef
>::WrapUnderCreateRule(
228 ::IOSurfaceCreate(props
.get()));
234 // Setup the correct YCbCr conversion matrix on the IOSurface, in case we pass
235 // this directly to CoreAnimation.
236 if (aColorSpace
== YUVColorSpace::BT601
) {
237 IOSurfaceSetValue(surfaceRef
.get(), CFSTR("IOSurfaceYCbCrMatrix"),
238 CFSTR("ITU_R_601_4"));
240 IOSurfaceSetValue(surfaceRef
.get(), CFSTR("IOSurfaceYCbCrMatrix"),
241 CFSTR("ITU_R_709_2"));
243 // Override the color space to be the same as the main display, so that
244 // CoreAnimation won't try to do any color correction (from the IOSurface
245 // space, to the display). In the future we may want to try specifying this
246 // correctly, but probably only once we do the same for videos drawn through
248 auto colorSpace
= CFTypeRefPtr
<CGColorSpaceRef
>::WrapUnderCreateRule(
249 CGDisplayCopyColorSpace(CGMainDisplayID()));
250 auto colorData
= CFTypeRefPtr
<CFDataRef
>::WrapUnderCreateRule(
251 CGColorSpaceCopyICCProfile(colorSpace
.get()));
252 IOSurfaceSetValue(surfaceRef
.get(), CFSTR("IOSurfaceColorSpace"),
255 RefPtr
<MacIOSurface
> ioSurface
=
256 new MacIOSurface(std::move(surfaceRef
), false, aColorSpace
);
258 return ioSurface
.forget();
262 already_AddRefed
<MacIOSurface
> MacIOSurface::LookupSurface(
263 IOSurfaceID aIOSurfaceID
, bool aHasAlpha
, gfx::YUVColorSpace aColorSpace
) {
264 CFTypeRefPtr
<IOSurfaceRef
> surfaceRef
=
265 CFTypeRefPtr
<IOSurfaceRef
>::WrapUnderCreateRule(
266 ::IOSurfaceLookup(aIOSurfaceID
));
267 if (!surfaceRef
) return nullptr;
269 RefPtr
<MacIOSurface
> ioSurface
=
270 new MacIOSurface(std::move(surfaceRef
), aHasAlpha
, aColorSpace
);
272 return ioSurface
.forget();
275 IOSurfaceID
MacIOSurface::GetIOSurfaceID() const {
276 return ::IOSurfaceGetID(mIOSurfaceRef
.get());
279 void* MacIOSurface::GetBaseAddress() const {
280 return ::IOSurfaceGetBaseAddress(mIOSurfaceRef
.get());
283 void* MacIOSurface::GetBaseAddressOfPlane(size_t aPlaneIndex
) const {
284 return ::IOSurfaceGetBaseAddressOfPlane(mIOSurfaceRef
.get(), aPlaneIndex
);
287 size_t MacIOSurface::GetWidth(size_t plane
) const {
288 return GetDevicePixelWidth(plane
);
291 size_t MacIOSurface::GetHeight(size_t plane
) const {
292 return GetDevicePixelHeight(plane
);
295 size_t MacIOSurface::GetPlaneCount() const {
296 return ::IOSurfaceGetPlaneCount(mIOSurfaceRef
.get());
300 size_t MacIOSurface::GetMaxWidth() {
301 return ::IOSurfaceGetPropertyMaximum(kIOSurfaceWidth
);
305 size_t MacIOSurface::GetMaxHeight() {
306 return ::IOSurfaceGetPropertyMaximum(kIOSurfaceHeight
);
309 size_t MacIOSurface::GetDevicePixelWidth(size_t plane
) const {
310 return ::IOSurfaceGetWidthOfPlane(mIOSurfaceRef
.get(), plane
);
313 size_t MacIOSurface::GetDevicePixelHeight(size_t plane
) const {
314 return ::IOSurfaceGetHeightOfPlane(mIOSurfaceRef
.get(), plane
);
317 size_t MacIOSurface::GetBytesPerRow(size_t plane
) const {
318 return ::IOSurfaceGetBytesPerRowOfPlane(mIOSurfaceRef
.get(), plane
);
321 size_t MacIOSurface::GetAllocSize() const {
322 return ::IOSurfaceGetAllocSize(mIOSurfaceRef
.get());
325 OSType
MacIOSurface::GetPixelFormat() const {
326 return ::IOSurfaceGetPixelFormat(mIOSurfaceRef
.get());
329 void MacIOSurface::IncrementUseCount() {
330 ::IOSurfaceIncrementUseCount(mIOSurfaceRef
.get());
333 void MacIOSurface::DecrementUseCount() {
334 ::IOSurfaceDecrementUseCount(mIOSurfaceRef
.get());
337 void MacIOSurface::Lock(bool aReadOnly
) {
338 MOZ_RELEASE_ASSERT(!mIsLocked
, "double MacIOSurface lock");
339 ::IOSurfaceLock(mIOSurfaceRef
.get(), aReadOnly
? kIOSurfaceLockReadOnly
: 0,
344 void MacIOSurface::Unlock(bool aReadOnly
) {
345 MOZ_RELEASE_ASSERT(mIsLocked
, "MacIOSurface unlock without being locked");
346 ::IOSurfaceUnlock(mIOSurfaceRef
.get(), aReadOnly
? kIOSurfaceLockReadOnly
: 0,
351 using mozilla::gfx::IntSize
;
352 using mozilla::gfx::SourceSurface
;
353 using mozilla::gfx::SurfaceFormat
;
355 static void MacIOSurfaceBufferDeallocator(void* aClosure
) {
356 MOZ_ASSERT(aClosure
);
358 delete[] static_cast<unsigned char*>(aClosure
);
361 already_AddRefed
<SourceSurface
> MacIOSurface::GetAsSurface() {
363 size_t bytesPerRow
= GetBytesPerRow();
364 size_t ioWidth
= GetDevicePixelWidth();
365 size_t ioHeight
= GetDevicePixelHeight();
367 unsigned char* ioData
= (unsigned char*)GetBaseAddress();
369 new unsigned char[bytesPerRow
* ioHeight
/ sizeof(unsigned char)];
370 for (size_t i
= 0; i
< ioHeight
; i
++) {
371 memcpy(dataCpy
+ i
* bytesPerRow
, ioData
+ i
* bytesPerRow
, ioWidth
* 4);
376 SurfaceFormat format
= HasAlpha() ? mozilla::gfx::SurfaceFormat::B8G8R8A8
377 : mozilla::gfx::SurfaceFormat::B8G8R8X8
;
379 RefPtr
<mozilla::gfx::DataSourceSurface
> surf
=
380 mozilla::gfx::Factory::CreateWrappingDataSourceSurface(
381 dataCpy
, bytesPerRow
, IntSize(ioWidth
, ioHeight
), format
,
382 &MacIOSurfaceBufferDeallocator
, static_cast<void*>(dataCpy
));
384 return surf
.forget();
387 already_AddRefed
<mozilla::gfx::DrawTarget
> MacIOSurface::GetAsDrawTargetLocked(
388 mozilla::gfx::BackendType aBackendType
) {
391 "Only call GetAsDrawTargetLocked while the surface is locked.");
393 size_t bytesPerRow
= GetBytesPerRow();
394 size_t ioWidth
= GetDevicePixelWidth();
395 size_t ioHeight
= GetDevicePixelHeight();
396 unsigned char* ioData
= (unsigned char*)GetBaseAddress();
397 SurfaceFormat format
= GetFormat();
398 return mozilla::gfx::Factory::CreateDrawTargetForData(
399 aBackendType
, ioData
, IntSize(ioWidth
, ioHeight
), bytesPerRow
, format
);
402 SurfaceFormat
MacIOSurface::GetFormat() const {
403 switch (GetPixelFormat()) {
404 case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
:
405 case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
:
406 return SurfaceFormat::NV12
;
407 case kCVPixelFormatType_422YpCbCr8_yuvs
:
408 case kCVPixelFormatType_422YpCbCr8FullRange
:
409 return SurfaceFormat::YUV422
;
410 case kCVPixelFormatType_32BGRA
:
411 return HasAlpha() ? SurfaceFormat::B8G8R8A8
: SurfaceFormat::B8G8R8X8
;
413 MOZ_ASSERT_UNREACHABLE("Unknown format");
414 return SurfaceFormat::B8G8R8A8
;
418 SurfaceFormat
MacIOSurface::GetReadFormat() const {
419 SurfaceFormat format
= GetFormat();
420 if (format
== SurfaceFormat::YUV422
) {
421 return SurfaceFormat::R8G8B8X8
;
426 CGLError
MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx
, GLenum target
,
427 GLenum internalFormat
,
428 GLsizei width
, GLsizei height
,
429 GLenum format
, GLenum type
,
430 GLuint plane
) const {
431 return ::CGLTexImageIOSurface2D(ctx
, target
, internalFormat
, width
, height
,
432 format
, type
, mIOSurfaceRef
.get(), plane
);
435 CGLError
MacIOSurface::CGLTexImageIOSurface2D(
436 mozilla::gl::GLContext
* aGL
, CGLContextObj ctx
, size_t plane
,
437 mozilla::gfx::SurfaceFormat
* aOutReadFormat
) {
438 MOZ_ASSERT(plane
>= 0);
439 bool isCompatibilityProfile
= aGL
->IsCompatibilityProfile();
440 OSType pixelFormat
= GetPixelFormat();
442 GLenum internalFormat
;
445 if (pixelFormat
== kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
||
446 pixelFormat
== kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
) {
447 MOZ_ASSERT(GetPlaneCount() == 2);
448 MOZ_ASSERT(plane
< 2);
450 // The LOCAL_GL_LUMINANCE and LOCAL_GL_LUMINANCE_ALPHA are the deprecated
451 // format. So, use LOCAL_GL_RED and LOCAL_GL_RB if we use core profile.
452 // https://www.khronos.org/opengl/wiki/Image_Format#Legacy_Image_Formats
454 internalFormat
= format
=
455 (isCompatibilityProfile
) ? (LOCAL_GL_LUMINANCE
) : (LOCAL_GL_RED
);
457 internalFormat
= format
=
458 (isCompatibilityProfile
) ? (LOCAL_GL_LUMINANCE_ALPHA
) : (LOCAL_GL_RG
);
460 type
= LOCAL_GL_UNSIGNED_BYTE
;
461 if (aOutReadFormat
) {
462 *aOutReadFormat
= mozilla::gfx::SurfaceFormat::NV12
;
464 } else if (pixelFormat
== kCVPixelFormatType_422YpCbCr8_yuvs
||
465 pixelFormat
== kCVPixelFormatType_422YpCbCr8FullRange
) {
466 MOZ_ASSERT(plane
== 0);
467 // The YCBCR_422_APPLE ext is only available in compatibility profile. So,
468 // we should use RGB_422_APPLE for core profile. The difference between
469 // YCBCR_422_APPLE and RGB_422_APPLE is that the YCBCR_422_APPLE converts
470 // the YCbCr value to RGB with REC 601 conversion. But the RGB_422_APPLE
471 // doesn't contain color conversion. You should do the color conversion by
472 // yourself for RGB_422_APPLE.
474 // https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_ycbcr_422.txt
475 // https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
476 if (isCompatibilityProfile
) {
477 format
= LOCAL_GL_YCBCR_422_APPLE
;
478 if (aOutReadFormat
) {
479 *aOutReadFormat
= mozilla::gfx::SurfaceFormat::R8G8B8X8
;
482 format
= LOCAL_GL_RGB_422_APPLE
;
483 if (aOutReadFormat
) {
484 *aOutReadFormat
= mozilla::gfx::SurfaceFormat::YUV422
;
487 internalFormat
= LOCAL_GL_RGB
;
488 type
= LOCAL_GL_UNSIGNED_SHORT_8_8_REV_APPLE
;
490 MOZ_ASSERT(plane
== 0);
492 internalFormat
= HasAlpha() ? LOCAL_GL_RGBA
: LOCAL_GL_RGB
;
493 format
= LOCAL_GL_BGRA
;
494 type
= LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV
;
495 if (aOutReadFormat
) {
496 *aOutReadFormat
= HasAlpha() ? mozilla::gfx::SurfaceFormat::R8G8B8A8
497 : mozilla::gfx::SurfaceFormat::R8G8B8X8
;
502 CGLTexImageIOSurface2D(ctx
, LOCAL_GL_TEXTURE_RECTANGLE_ARB
,
503 internalFormat
, GetDevicePixelWidth(plane
),
504 GetDevicePixelHeight(plane
), format
, type
, plane
);
506 const auto formatChars
= (const char*)&pixelFormat
;
507 const char formatStr
[] = {formatChars
[3], formatChars
[2], formatChars
[1],
509 const nsPrintfCString
errStr(
510 "CGLTexImageIOSurface2D(context, target, 0x%04x,"
511 " %u, %u, 0x%04x, 0x%04x, iosurfPtr, %u) -> %i",
512 internalFormat
, uint32_t(GetDevicePixelWidth(plane
)),
513 uint32_t(GetDevicePixelHeight(plane
)), format
, type
,
514 (unsigned int)plane
, err
);
515 gfxCriticalError() << errStr
.get() << " (iosurf format: " << formatStr