|
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 "GLScreenBuffer.h" |
|
7 |
|
8 #include <cstring> |
|
9 #include "gfxImageSurface.h" |
|
10 #include "GLContext.h" |
|
11 #include "GLBlitHelper.h" |
|
12 #include "GLReadTexImageHelper.h" |
|
13 #include "SharedSurfaceGL.h" |
|
14 #include "SurfaceStream.h" |
|
15 #ifdef MOZ_WIDGET_GONK |
|
16 #include "SharedSurfaceGralloc.h" |
|
17 #include "nsXULAppAPI.h" |
|
18 #endif |
|
19 #ifdef XP_MACOSX |
|
20 #include "SharedSurfaceIO.h" |
|
21 #endif |
|
22 #include "ScopedGLHelpers.h" |
|
23 #include "gfx2DGlue.h" |
|
24 |
|
25 using namespace mozilla::gfx; |
|
26 |
|
27 namespace mozilla { |
|
28 namespace gl { |
|
29 |
|
30 GLScreenBuffer* |
|
31 GLScreenBuffer::Create(GLContext* gl, |
|
32 const gfx::IntSize& size, |
|
33 const SurfaceCaps& caps) |
|
34 { |
|
35 if (caps.antialias && |
|
36 !gl->IsSupported(GLFeature::framebuffer_multisample)) |
|
37 { |
|
38 return nullptr; |
|
39 } |
|
40 |
|
41 SurfaceFactory_GL* factory = nullptr; |
|
42 |
|
43 #ifdef MOZ_WIDGET_GONK |
|
44 /* On B2G, we want a Gralloc factory, and we want one right at the start */ |
|
45 if (!factory && |
|
46 caps.surfaceAllocator && |
|
47 XRE_GetProcessType() != GeckoProcessType_Default) |
|
48 { |
|
49 factory = new SurfaceFactory_Gralloc(gl, caps); |
|
50 } |
|
51 #endif |
|
52 #ifdef XP_MACOSX |
|
53 /* On OSX, we want an IOSurface factory, and we want one right at the start */ |
|
54 if (!factory) |
|
55 { |
|
56 factory = new SurfaceFactory_IOSurface(gl, caps); |
|
57 } |
|
58 #endif |
|
59 |
|
60 if (!factory) |
|
61 factory = new SurfaceFactory_Basic(gl, caps); |
|
62 |
|
63 SurfaceStream* stream = SurfaceStream::CreateForType( |
|
64 SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread, |
|
65 caps.preserve), |
|
66 gl, |
|
67 nullptr); |
|
68 |
|
69 return new GLScreenBuffer(gl, caps, factory, stream); |
|
70 } |
|
71 |
|
72 GLScreenBuffer::~GLScreenBuffer() |
|
73 { |
|
74 delete mDraw; |
|
75 delete mRead; |
|
76 |
|
77 // bug 914823: it is crucial to destroy the Factory _after_ we destroy |
|
78 // the SharedSurfaces around here! Reason: the shared surfaces will want |
|
79 // to ask the Allocator (e.g. the ClientLayerManager) to destroy their |
|
80 // buffers, but that Allocator may be kept alive by the Factory, |
|
81 // as it currently the case in SurfaceFactory_Gralloc holding a nsRefPtr |
|
82 // to the Allocator! |
|
83 delete mFactory; |
|
84 } |
|
85 |
|
86 |
|
87 void |
|
88 GLScreenBuffer::BindAsFramebuffer(GLContext* const gl, GLenum target) const |
|
89 { |
|
90 GLuint drawFB = DrawFB(); |
|
91 GLuint readFB = ReadFB(); |
|
92 |
|
93 if (!gl->IsSupported(GLFeature::framebuffer_blit)) { |
|
94 MOZ_ASSERT(drawFB == readFB); |
|
95 gl->raw_fBindFramebuffer(target, readFB); |
|
96 return; |
|
97 } |
|
98 |
|
99 switch (target) { |
|
100 case LOCAL_GL_FRAMEBUFFER: |
|
101 gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB); |
|
102 gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB); |
|
103 break; |
|
104 |
|
105 case LOCAL_GL_DRAW_FRAMEBUFFER_EXT: |
|
106 if (!gl->IsSupported(GLFeature::framebuffer_blit)) |
|
107 NS_WARNING("DRAW_FRAMEBUFFER requested but unavailable."); |
|
108 |
|
109 gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB); |
|
110 break; |
|
111 |
|
112 case LOCAL_GL_READ_FRAMEBUFFER_EXT: |
|
113 if (!gl->IsSupported(GLFeature::framebuffer_blit)) |
|
114 NS_WARNING("READ_FRAMEBUFFER requested but unavailable."); |
|
115 |
|
116 gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB); |
|
117 break; |
|
118 |
|
119 default: |
|
120 MOZ_CRASH("Bad `target` for BindFramebuffer."); |
|
121 } |
|
122 } |
|
123 |
|
124 void |
|
125 GLScreenBuffer::BindFB(GLuint fb) |
|
126 { |
|
127 GLuint drawFB = DrawFB(); |
|
128 GLuint readFB = ReadFB(); |
|
129 |
|
130 mUserDrawFB = fb; |
|
131 mUserReadFB = fb; |
|
132 mInternalDrawFB = (fb == 0) ? drawFB : fb; |
|
133 mInternalReadFB = (fb == 0) ? readFB : fb; |
|
134 |
|
135 if (mInternalDrawFB == mInternalReadFB) { |
|
136 mGL->raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mInternalDrawFB); |
|
137 } else { |
|
138 MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); |
|
139 mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); |
|
140 mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); |
|
141 } |
|
142 |
|
143 #ifdef DEBUG |
|
144 mInInternalMode_DrawFB = false; |
|
145 mInInternalMode_ReadFB = false; |
|
146 #endif |
|
147 } |
|
148 |
|
149 void |
|
150 GLScreenBuffer::BindDrawFB(GLuint fb) |
|
151 { |
|
152 if (!mGL->IsSupported(GLFeature::framebuffer_blit)) { |
|
153 NS_WARNING("DRAW_FRAMEBUFFER requested, but unsupported."); |
|
154 |
|
155 mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, fb); |
|
156 } else { |
|
157 GLuint drawFB = DrawFB(); |
|
158 mUserDrawFB = fb; |
|
159 mInternalDrawFB = (fb == 0) ? drawFB : fb; |
|
160 |
|
161 mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); |
|
162 } |
|
163 |
|
164 #ifdef DEBUG |
|
165 mInInternalMode_DrawFB = false; |
|
166 #endif |
|
167 } |
|
168 |
|
169 void |
|
170 GLScreenBuffer::BindReadFB(GLuint fb) |
|
171 { |
|
172 if (!mGL->IsSupported(GLFeature::framebuffer_blit)) { |
|
173 NS_WARNING("READ_FRAMEBUFFER requested, but unsupported."); |
|
174 |
|
175 mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, fb); |
|
176 } else { |
|
177 GLuint readFB = ReadFB(); |
|
178 mUserReadFB = fb; |
|
179 mInternalReadFB = (fb == 0) ? readFB : fb; |
|
180 |
|
181 mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); |
|
182 } |
|
183 |
|
184 #ifdef DEBUG |
|
185 mInInternalMode_ReadFB = false; |
|
186 #endif |
|
187 } |
|
188 |
|
189 void |
|
190 GLScreenBuffer::BindDrawFB_Internal(GLuint fb) |
|
191 { |
|
192 mInternalDrawFB = mUserDrawFB = fb; |
|
193 mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); |
|
194 |
|
195 #ifdef DEBUG |
|
196 mInInternalMode_DrawFB = true; |
|
197 #endif |
|
198 } |
|
199 |
|
200 void |
|
201 GLScreenBuffer::BindReadFB_Internal(GLuint fb) |
|
202 { |
|
203 mInternalReadFB = mUserReadFB = fb; |
|
204 mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); |
|
205 |
|
206 #ifdef DEBUG |
|
207 mInInternalMode_ReadFB = true; |
|
208 #endif |
|
209 } |
|
210 |
|
211 |
|
212 GLuint |
|
213 GLScreenBuffer::GetDrawFB() const |
|
214 { |
|
215 #ifdef DEBUG |
|
216 MOZ_ASSERT(mGL->IsCurrent()); |
|
217 MOZ_ASSERT(!mInInternalMode_DrawFB); |
|
218 |
|
219 // Don't need a branch here, because: |
|
220 // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT == LOCAL_GL_FRAMEBUFFER_BINDING == 0x8CA6 |
|
221 // We use raw_ here because this is debug code and we need to see what |
|
222 // the driver thinks. |
|
223 GLuint actual = 0; |
|
224 mGL->raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual); |
|
225 |
|
226 GLuint predicted = mInternalDrawFB; |
|
227 if (predicted != actual) { |
|
228 printf_stderr("Misprediction: Bound draw FB predicted: %d. Was: %d.\n", |
|
229 predicted, actual); |
|
230 MOZ_ASSERT(false, "Draw FB binding misprediction!"); |
|
231 } |
|
232 #endif |
|
233 |
|
234 return mUserDrawFB; |
|
235 } |
|
236 |
|
237 GLuint |
|
238 GLScreenBuffer::GetReadFB() const |
|
239 { |
|
240 #ifdef DEBUG |
|
241 MOZ_ASSERT(mGL->IsCurrent()); |
|
242 MOZ_ASSERT(!mInInternalMode_ReadFB); |
|
243 |
|
244 // We use raw_ here because this is debug code and we need to see what |
|
245 // the driver thinks. |
|
246 GLuint actual = 0; |
|
247 if (mGL->IsSupported(GLFeature::framebuffer_blit)) |
|
248 mGL->raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual); |
|
249 else |
|
250 mGL->raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)&actual); |
|
251 |
|
252 GLuint predicted = mInternalReadFB; |
|
253 if (predicted != actual) { |
|
254 printf_stderr("Misprediction: Bound read FB predicted: %d. Was: %d.\n", |
|
255 predicted, actual); |
|
256 MOZ_ASSERT(false, "Read FB binding misprediction!"); |
|
257 } |
|
258 #endif |
|
259 |
|
260 return mUserReadFB; |
|
261 } |
|
262 |
|
263 GLuint |
|
264 GLScreenBuffer::GetFB() const |
|
265 { |
|
266 MOZ_ASSERT(GetDrawFB() == GetReadFB()); |
|
267 return GetDrawFB(); |
|
268 } |
|
269 |
|
270 |
|
271 void |
|
272 GLScreenBuffer::DeletingFB(GLuint fb) |
|
273 { |
|
274 if (fb == mInternalDrawFB) { |
|
275 mInternalDrawFB = 0; |
|
276 mUserDrawFB = 0; |
|
277 } |
|
278 if (fb == mInternalReadFB) { |
|
279 mInternalReadFB = 0; |
|
280 mUserReadFB = 0; |
|
281 } |
|
282 } |
|
283 |
|
284 |
|
285 void |
|
286 GLScreenBuffer::AfterDrawCall() |
|
287 { |
|
288 if (mUserDrawFB != 0) |
|
289 return; |
|
290 |
|
291 RequireBlit(); |
|
292 } |
|
293 |
|
294 void |
|
295 GLScreenBuffer::BeforeReadCall() |
|
296 { |
|
297 if (mUserReadFB != 0) |
|
298 return; |
|
299 |
|
300 AssureBlitted(); |
|
301 } |
|
302 |
|
303 bool |
|
304 GLScreenBuffer::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, |
|
305 GLenum format, GLenum type, GLvoid *pixels) |
|
306 { |
|
307 // If the currently bound framebuffer is backed by a SharedSurface_GL |
|
308 // then it might want to override how we read pixel data from it. |
|
309 // This is normally only the default framebuffer, but we can also |
|
310 // have SharedSurfaces bound to other framebuffers when doing |
|
311 // readback for BasicLayers. |
|
312 SharedSurface_GL* surf; |
|
313 if (GetReadFB() == 0) { |
|
314 surf = SharedSurf(); |
|
315 } else { |
|
316 surf = mGL->mFBOMapping[GetReadFB()]; |
|
317 } |
|
318 if (surf) { |
|
319 return surf->ReadPixels(x, y, width, height, format, type, pixels); |
|
320 } |
|
321 |
|
322 return false; |
|
323 } |
|
324 |
|
325 void |
|
326 GLScreenBuffer::RequireBlit() |
|
327 { |
|
328 mNeedsBlit = true; |
|
329 } |
|
330 |
|
331 void |
|
332 GLScreenBuffer::AssureBlitted() |
|
333 { |
|
334 if (!mNeedsBlit) |
|
335 return; |
|
336 |
|
337 if (mDraw) { |
|
338 GLuint drawFB = DrawFB(); |
|
339 GLuint readFB = ReadFB(); |
|
340 |
|
341 MOZ_ASSERT(drawFB != 0); |
|
342 MOZ_ASSERT(drawFB != readFB); |
|
343 MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); |
|
344 MOZ_ASSERT(mDraw->Size() == mRead->Size()); |
|
345 |
|
346 ScopedBindFramebuffer boundFB(mGL); |
|
347 ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false); |
|
348 |
|
349 BindReadFB_Internal(drawFB); |
|
350 BindDrawFB_Internal(readFB); |
|
351 |
|
352 const gfx::IntSize& srcSize = mDraw->Size(); |
|
353 const gfx::IntSize& destSize = mRead->Size(); |
|
354 |
|
355 mGL->raw_fBlitFramebuffer(0, 0, srcSize.width, srcSize.height, |
|
356 0, 0, destSize.width, destSize.height, |
|
357 LOCAL_GL_COLOR_BUFFER_BIT, |
|
358 LOCAL_GL_NEAREST); |
|
359 // Done! |
|
360 } |
|
361 |
|
362 mNeedsBlit = false; |
|
363 } |
|
364 |
|
365 void |
|
366 GLScreenBuffer::Morph(SurfaceFactory_GL* newFactory, SurfaceStreamType streamType) |
|
367 { |
|
368 MOZ_ASSERT(mStream); |
|
369 |
|
370 if (newFactory) { |
|
371 delete mFactory; |
|
372 mFactory = newFactory; |
|
373 } |
|
374 |
|
375 if (mStream->mType == streamType) |
|
376 return; |
|
377 |
|
378 SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mGL, mStream); |
|
379 MOZ_ASSERT(newStream); |
|
380 |
|
381 mStream = newStream; |
|
382 } |
|
383 |
|
384 void |
|
385 GLScreenBuffer::Attach(SharedSurface* surface, const gfx::IntSize& size) |
|
386 { |
|
387 ScopedBindFramebuffer autoFB(mGL); |
|
388 |
|
389 SharedSurface_GL* surf = SharedSurface_GL::Cast(surface); |
|
390 if (mRead && SharedSurf()) |
|
391 SharedSurf()->UnlockProd(); |
|
392 |
|
393 surf->LockProd(); |
|
394 |
|
395 if (mRead && |
|
396 surf->AttachType() == SharedSurf()->AttachType() && |
|
397 size == Size()) |
|
398 { |
|
399 // Same size, same type, ready for reuse! |
|
400 mRead->Attach(surf); |
|
401 } else { |
|
402 // Else something changed, so resize: |
|
403 DrawBuffer* draw = CreateDraw(size); // Can be null. |
|
404 ReadBuffer* read = CreateRead(surf); |
|
405 MOZ_ASSERT(read); // Should never fail if SwapProd succeeded. |
|
406 |
|
407 delete mDraw; |
|
408 delete mRead; |
|
409 |
|
410 mDraw = draw; |
|
411 mRead = read; |
|
412 } |
|
413 |
|
414 // Check that we're all set up. |
|
415 MOZ_ASSERT(SharedSurf() == surf); |
|
416 |
|
417 if (!PreserveBuffer()) { |
|
418 // DiscardFramebuffer here could help perf on some mobile platforms. |
|
419 } |
|
420 } |
|
421 |
|
422 bool |
|
423 GLScreenBuffer::Swap(const gfx::IntSize& size) |
|
424 { |
|
425 SharedSurface* nextSurf = mStream->SwapProducer(mFactory, size); |
|
426 if (!nextSurf) { |
|
427 SurfaceFactory_Basic basicFactory(mGL, mFactory->Caps()); |
|
428 nextSurf = mStream->SwapProducer(&basicFactory, size); |
|
429 if (!nextSurf) |
|
430 return false; |
|
431 |
|
432 NS_WARNING("SwapProd failed for sophisticated Factory type, fell back to Basic."); |
|
433 } |
|
434 MOZ_ASSERT(nextSurf); |
|
435 |
|
436 Attach(nextSurf, size); |
|
437 |
|
438 return true; |
|
439 } |
|
440 |
|
441 bool |
|
442 GLScreenBuffer::PublishFrame(const gfx::IntSize& size) |
|
443 { |
|
444 AssureBlitted(); |
|
445 |
|
446 bool good = Swap(size); |
|
447 return good; |
|
448 } |
|
449 |
|
450 bool |
|
451 GLScreenBuffer::Resize(const gfx::IntSize& size) |
|
452 { |
|
453 SharedSurface* surface = mStream->Resize(mFactory, size); |
|
454 if (!surface) |
|
455 return false; |
|
456 |
|
457 Attach(surface, size); |
|
458 return true; |
|
459 } |
|
460 |
|
461 DrawBuffer* |
|
462 GLScreenBuffer::CreateDraw(const gfx::IntSize& size) |
|
463 { |
|
464 GLContext* gl = mFactory->GL(); |
|
465 const GLFormats& formats = mFactory->Formats(); |
|
466 const SurfaceCaps& caps = mFactory->DrawCaps(); |
|
467 |
|
468 return DrawBuffer::Create(gl, caps, formats, size); |
|
469 } |
|
470 |
|
471 ReadBuffer* |
|
472 GLScreenBuffer::CreateRead(SharedSurface_GL* surf) |
|
473 { |
|
474 GLContext* gl = mFactory->GL(); |
|
475 const GLFormats& formats = mFactory->Formats(); |
|
476 const SurfaceCaps& caps = mFactory->ReadCaps(); |
|
477 |
|
478 return ReadBuffer::Create(gl, caps, formats, surf); |
|
479 } |
|
480 |
|
481 void |
|
482 GLScreenBuffer::Readback(SharedSurface_GL* src, DataSourceSurface* dest) |
|
483 { |
|
484 MOZ_ASSERT(src && dest); |
|
485 DataSourceSurface::MappedSurface ms; |
|
486 dest->Map(DataSourceSurface::MapType::READ, &ms); |
|
487 nsRefPtr<gfxImageSurface> wrappedDest = |
|
488 new gfxImageSurface(ms.mData, |
|
489 ThebesIntSize(dest->GetSize()), |
|
490 ms.mStride, |
|
491 SurfaceFormatToImageFormat(dest->GetFormat())); |
|
492 DeprecatedReadback(src, wrappedDest); |
|
493 dest->Unmap(); |
|
494 } |
|
495 |
|
496 void |
|
497 GLScreenBuffer::DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest) |
|
498 { |
|
499 MOZ_ASSERT(src && dest); |
|
500 MOZ_ASSERT(ToIntSize(dest->GetSize()) == src->Size()); |
|
501 MOZ_ASSERT(dest->Format() == (src->HasAlpha() ? gfxImageFormat::ARGB32 |
|
502 : gfxImageFormat::RGB24)); |
|
503 |
|
504 mGL->MakeCurrent(); |
|
505 |
|
506 bool needsSwap = src != SharedSurf(); |
|
507 if (needsSwap) { |
|
508 SharedSurf()->UnlockProd(); |
|
509 src->LockProd(); |
|
510 } |
|
511 |
|
512 ReadBuffer* buffer = CreateRead(src); |
|
513 MOZ_ASSERT(buffer); |
|
514 |
|
515 ScopedBindFramebuffer autoFB(mGL, buffer->FB()); |
|
516 ReadPixelsIntoImageSurface(mGL, dest); |
|
517 |
|
518 delete buffer; |
|
519 |
|
520 if (needsSwap) { |
|
521 src->UnlockProd(); |
|
522 SharedSurf()->LockProd(); |
|
523 } |
|
524 } |
|
525 |
|
526 DrawBuffer* |
|
527 DrawBuffer::Create(GLContext* const gl, |
|
528 const SurfaceCaps& caps, |
|
529 const GLFormats& formats, |
|
530 const gfx::IntSize& size) |
|
531 { |
|
532 if (!caps.color) { |
|
533 MOZ_ASSERT(!caps.alpha && !caps.depth && !caps.stencil); |
|
534 |
|
535 // Nothing is needed. |
|
536 return nullptr; |
|
537 } |
|
538 |
|
539 GLuint colorMSRB = 0; |
|
540 GLuint depthRB = 0; |
|
541 GLuint stencilRB = 0; |
|
542 |
|
543 GLuint* pColorMSRB = caps.antialias ? &colorMSRB : nullptr; |
|
544 GLuint* pDepthRB = caps.depth ? &depthRB : nullptr; |
|
545 GLuint* pStencilRB = caps.stencil ? &stencilRB : nullptr; |
|
546 |
|
547 if (!formats.color_rbFormat) |
|
548 pColorMSRB = nullptr; |
|
549 |
|
550 if (pDepthRB && pStencilRB) { |
|
551 if (!formats.depth && !formats.depthStencil) |
|
552 pDepthRB = nullptr; |
|
553 |
|
554 if (!formats.stencil && !formats.depthStencil) |
|
555 pStencilRB = nullptr; |
|
556 } else { |
|
557 if (!formats.depth) |
|
558 pDepthRB = nullptr; |
|
559 |
|
560 if (!formats.stencil) |
|
561 pStencilRB = nullptr; |
|
562 } |
|
563 |
|
564 CreateRenderbuffersForOffscreen(gl, formats, size, caps.antialias, |
|
565 pColorMSRB, pDepthRB, pStencilRB); |
|
566 |
|
567 GLuint fb = 0; |
|
568 gl->fGenFramebuffers(1, &fb); |
|
569 gl->AttachBuffersToFB(0, colorMSRB, depthRB, stencilRB, fb); |
|
570 MOZ_ASSERT(gl->IsFramebufferComplete(fb)); |
|
571 |
|
572 return new DrawBuffer(gl, size, fb, colorMSRB, depthRB, stencilRB); |
|
573 } |
|
574 |
|
575 DrawBuffer::~DrawBuffer() |
|
576 { |
|
577 mGL->MakeCurrent(); |
|
578 |
|
579 GLuint fb = mFB; |
|
580 GLuint rbs[] = { |
|
581 mColorMSRB, |
|
582 mDepthRB, |
|
583 mStencilRB |
|
584 }; |
|
585 |
|
586 mGL->fDeleteFramebuffers(1, &fb); |
|
587 mGL->fDeleteRenderbuffers(3, rbs); |
|
588 } |
|
589 |
|
590 |
|
591 |
|
592 |
|
593 |
|
594 |
|
595 ReadBuffer* |
|
596 ReadBuffer::Create(GLContext* gl, |
|
597 const SurfaceCaps& caps, |
|
598 const GLFormats& formats, |
|
599 SharedSurface_GL* surf) |
|
600 { |
|
601 MOZ_ASSERT(surf); |
|
602 |
|
603 if (surf->AttachType() == AttachmentType::Screen) { |
|
604 // Don't need anything. Our read buffer will be the 'screen'. |
|
605 |
|
606 return new ReadBuffer(gl, |
|
607 0, 0, 0, |
|
608 surf); |
|
609 } |
|
610 |
|
611 GLuint depthRB = 0; |
|
612 GLuint stencilRB = 0; |
|
613 |
|
614 GLuint* pDepthRB = caps.depth ? &depthRB : nullptr; |
|
615 GLuint* pStencilRB = caps.stencil ? &stencilRB : nullptr; |
|
616 |
|
617 CreateRenderbuffersForOffscreen(gl, formats, surf->Size(), caps.antialias, |
|
618 nullptr, pDepthRB, pStencilRB); |
|
619 |
|
620 GLuint colorTex = 0; |
|
621 GLuint colorRB = 0; |
|
622 GLenum target = 0; |
|
623 |
|
624 switch (surf->AttachType()) { |
|
625 case AttachmentType::GLTexture: |
|
626 colorTex = surf->ProdTexture(); |
|
627 target = surf->ProdTextureTarget(); |
|
628 break; |
|
629 case AttachmentType::GLRenderbuffer: |
|
630 colorRB = surf->ProdRenderbuffer(); |
|
631 break; |
|
632 default: |
|
633 MOZ_CRASH("Unknown attachment type?"); |
|
634 } |
|
635 MOZ_ASSERT(colorTex || colorRB); |
|
636 |
|
637 GLuint fb = 0; |
|
638 gl->fGenFramebuffers(1, &fb); |
|
639 gl->AttachBuffersToFB(colorTex, colorRB, depthRB, stencilRB, fb, target); |
|
640 gl->mFBOMapping[fb] = surf; |
|
641 |
|
642 MOZ_ASSERT(gl->IsFramebufferComplete(fb)); |
|
643 |
|
644 return new ReadBuffer(gl, |
|
645 fb, depthRB, stencilRB, |
|
646 surf); |
|
647 } |
|
648 |
|
649 ReadBuffer::~ReadBuffer() |
|
650 { |
|
651 mGL->MakeCurrent(); |
|
652 |
|
653 GLuint fb = mFB; |
|
654 GLuint rbs[] = { |
|
655 mDepthRB, |
|
656 mStencilRB |
|
657 }; |
|
658 |
|
659 mGL->fDeleteFramebuffers(1, &fb); |
|
660 mGL->fDeleteRenderbuffers(2, rbs); |
|
661 mGL->mFBOMapping.erase(mFB); |
|
662 } |
|
663 |
|
664 void |
|
665 ReadBuffer::Attach(SharedSurface_GL* surf) |
|
666 { |
|
667 MOZ_ASSERT(surf && mSurf); |
|
668 MOZ_ASSERT(surf->AttachType() == mSurf->AttachType()); |
|
669 MOZ_ASSERT(surf->Size() == mSurf->Size()); |
|
670 |
|
671 // Nothing else is needed for AttachType Screen. |
|
672 if (surf->AttachType() != AttachmentType::Screen) { |
|
673 GLuint colorTex = 0; |
|
674 GLuint colorRB = 0; |
|
675 GLenum target = 0; |
|
676 |
|
677 switch (surf->AttachType()) { |
|
678 case AttachmentType::GLTexture: |
|
679 colorTex = surf->ProdTexture(); |
|
680 target = surf->ProdTextureTarget(); |
|
681 break; |
|
682 case AttachmentType::GLRenderbuffer: |
|
683 colorRB = surf->ProdRenderbuffer(); |
|
684 break; |
|
685 default: |
|
686 MOZ_CRASH("Unknown attachment type?"); |
|
687 } |
|
688 |
|
689 mGL->AttachBuffersToFB(colorTex, colorRB, 0, 0, mFB, target); |
|
690 mGL->mFBOMapping[mFB] = surf; |
|
691 MOZ_ASSERT(mGL->IsFramebufferComplete(mFB)); |
|
692 } |
|
693 |
|
694 mSurf = surf; |
|
695 } |
|
696 |
|
697 const gfx::IntSize& |
|
698 ReadBuffer::Size() const |
|
699 { |
|
700 return mSurf->Size(); |
|
701 } |
|
702 |
|
703 } /* namespace gl */ |
|
704 } /* namespace mozilla */ |