Index: cc/gl_renderer.cc |
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc |
index 9bb2fdeff6f91ddfe986298c2f6297aba5780d0e..6c7ba24fc1961c523187b5f237c86193703ea77f 100644 |
--- a/cc/gl_renderer.cc |
+++ b/cc/gl_renderer.cc |
@@ -14,6 +14,7 @@ |
#include "base/string_util.h" |
#include "build/build_config.h" |
#include "cc/compositor_frame.h" |
+#include "cc/compositor_frame_ack.h" |
#include "cc/compositor_frame_metadata.h" |
#include "cc/damage_tracker.h" |
#include "cc/geometry_binding.h" |
@@ -83,8 +84,10 @@ GLRenderer::GLRenderer(RendererClient* client, OutputSurface* outputSurface, Res |
, m_isUsingBindUniform(false) |
, m_visible(true) |
, m_isScissorEnabled(false) |
+ , m_renderToMailbox(outputSurface->Capabilities().render_to_mailbox) |
{ |
DCHECK(m_context); |
+ m_pendingFrames.push_back(MailboxTexture()); |
} |
bool GLRenderer::initialize() |
@@ -153,6 +156,10 @@ GLRenderer::~GLRenderer() |
m_context->setMemoryAllocationChangedCallbackCHROMIUM(0); |
m_context->setContextLostCallback(0); |
cleanupSharedObjects(); |
+ |
+ DCHECK(m_pendingFrames.size() == 1); |
piman
2013/01/18 02:14:11
What ensures that this doesn't get deleted while a
|
+ if (m_pendingFrames.back().textureId) |
+ m_context->deleteTexture(m_pendingFrames.back().textureId); |
} |
const RendererCapabilities& GLRenderer::capabilities() const |
@@ -206,6 +213,43 @@ void GLRenderer::viewportChanged() |
m_isViewportChanged = true; |
} |
+void GLRenderer::receiveCompositorFrameAck(const CompositorFrameAck& ack) |
+{ |
+ if (m_renderToMailbox) { |
danakj
2013/01/18 01:01:41
if (!m_renderToMailbox)
return;
|
+ onSwapBuffersComplete(); |
Sami
2013/01/25 23:17:27
Should we consume the texture and insert the sync
|
+ |
+ DCHECK(m_pendingFrames.size()); |
+ if (!ack.mailbox.isZero()) { |
+ std::vector<MailboxTexture>::iterator it = m_pendingFrames.begin(); |
+ for (; it != m_pendingFrames.end(); it++) { |
danakj
2013/01/18 01:01:41
shouldn't the frame always be the .front() here, s
no sievers
2013/01/18 01:14:54
The one exception is skipped frames. When RWHV dec
|
+ if (!memcmp(ack.mailbox.name, it->mailbox.name, sizeof(Mailbox::name))) |
+ break; |
+ } |
+ CHECK(it != m_pendingFrames.end()); |
+ MailboxTexture& texture = *it; |
+ |
+ DCHECK(texture.textureId); |
danakj
2013/01/18 01:01:41
if you like, i think you could create a texture id
|
+ m_context->bindTexture(GL_TEXTURE_2D, texture.textureId); |
+ |
+ // If the consumer is bouncing back the same texture (i.e. skipping the frame), |
+ // we don't have to synchronize here (sync_point == 0). |
+ if (ack.sync_point) |
+ m_context->waitSyncPoint(ack.sync_point); |
+ |
+ m_context->consumeTextureCHROMIUM(GL_TEXTURE_2D, ack.mailbox.name); |
+ m_returnedTextures.push(texture); |
+ m_pendingFrames.erase(it); |
+ } else { |
+ // Either this is the very first ACK or the oldest buffer is not being returned |
+ // because the frontbuffer was discarded in the browser. |
+ MailboxTexture& texture = m_pendingFrames.front(); |
+ if (texture.textureId) |
+ m_context->deleteTexture(texture.textureId); |
+ m_pendingFrames.erase(m_pendingFrames.begin()); |
+ } |
+ } |
+} |
+ |
void GLRenderer::clearFramebuffer(DrawingFrame& frame) |
{ |
// On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen. |
@@ -235,6 +279,11 @@ void GLRenderer::beginDrawingFrame(DrawingFrame& frame) |
// viewport size is never set. |
m_isViewportChanged = false; |
m_context->reshape(viewportWidth(), viewportHeight()); |
+ |
+ if (m_renderToMailbox) { |
+ discardBackbuffer(); |
+ ensureBackbuffer(); |
+ } |
} |
makeContextCurrent(); |
@@ -1176,7 +1225,24 @@ void GLRenderer::finishDrawingFrame(DrawingFrame& frame) |
CompositorFrame compositor_frame; |
compositor_frame.metadata = m_client->makeCompositorFrameMetadata(); |
compositor_frame.gl_frame_data.reset(new GLFrameData()); |
- // FIXME: Fill in GLFrameData when we implement swapping with it. |
+ |
+ if (m_renderToMailbox) { |
+ // In non-threaded mode there is no swap throttling yet. |
+ DCHECK(m_client->hasImplThread()); |
+ |
+ DCHECK(!viewportSize().IsEmpty()); |
+ DCHECK(!m_currentBacking.mailbox.isZero()); |
+ GLC(m_context, m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0)); |
+ context()->bindTexture(GL_TEXTURE_2D, m_currentBacking.textureId); |
+ context()->produceTextureCHROMIUM(GL_TEXTURE_2D, m_currentBacking.mailbox.name); |
+ compositor_frame.gl_frame_data->mailbox = m_currentBacking.mailbox; |
+ compositor_frame.gl_frame_data->size = m_currentBacking.size; |
+ DCHECK(viewportSize() == m_currentBacking.size); |
+ compositor_frame.gl_frame_data->sync_point = context()->insertSyncPoint(); |
+ m_pendingFrames.push_back(m_currentBacking); |
+ m_currentBacking = MailboxTexture(); |
+ } |
+ |
m_outputSurface->SendFrameToParentCompositor(&compositor_frame); |
} |
} |
@@ -1306,7 +1372,10 @@ bool GLRenderer::swapBuffers() |
} else { |
// Note that currently this has the same effect as swapBuffers; we should |
// consider exposing a different entry point on WebGraphicsContext3D. |
- m_context->prepareTexture(); |
+ if (m_renderToMailbox) |
+ m_context->flush(); |
piman
2013/01/18 02:14:11
We definitely also want to support the partial swa
Sami
2013/01/25 23:17:27
Is it necessary to flush after inserting a sync po
piman
2013/01/25 23:44:56
The flush isn't necessary to ensure the sync point
Sami
2013/01/26 00:30:27
Thanks for the explanation. I was just wondering w
piman
2013/01/26 00:37:35
It does an implicit shallow flush FWIW, to ensure
|
+ else |
+ m_context->prepareTexture(); |
} |
m_swapBufferRect = gfx::Rect(); |
@@ -1374,13 +1443,28 @@ void GLRenderer::enforceMemoryPolicy() |
void GLRenderer::discardBackbuffer() |
{ |
- if (m_isBackbufferDiscarded) |
- return; |
+ if (m_renderToMailbox && m_currentBacking.textureId) { |
+ if (m_currentBacking.textureId) { |
+ context()->deleteTexture(m_currentBacking.textureId); |
+ m_currentBacking.textureId = 0; |
+ m_currentBacking.mailbox = Mailbox(); |
+ } |
- if (!m_capabilities.usingDiscardBackbuffer) |
- return; |
+ while (m_returnedTextures.size()) { |
+ m_context->deleteTexture(m_returnedTextures.front()); |
+ m_returnedTextures.pop(); |
+ } |
+ |
+ } else { |
+ if (m_isBackbufferDiscarded) |
+ return; |
+ |
+ if (!m_capabilities.usingDiscardBackbuffer) |
+ return; |
+ |
+ m_context->discardBackbufferCHROMIUM(); |
+ } |
- m_context->discardBackbufferCHROMIUM(); |
m_isBackbufferDiscarded = true; |
// Damage tracker needs a full reset every time framebuffer is discarded. |
@@ -1389,13 +1473,44 @@ void GLRenderer::discardBackbuffer() |
void GLRenderer::ensureBackbuffer() |
{ |
- if (!m_isBackbufferDiscarded) |
- return; |
+ if (m_renderToMailbox) { |
+ if (!m_currentBacking.textureId) { |
+ while (m_returnedTextures.size()) { |
+ MailboxTexture& texture = m_returnedTextures.front(); |
+ if (texture.size == viewportSize()) { |
+ m_currentBacking = texture; |
+ m_returnedTextures.pop(); |
+ break; |
+ } |
+ |
+ m_context->deleteTexture(texture.textureId); |
+ m_returnedTextures.pop(); |
+ } |
+ |
+ if (!m_currentBacking.textureId) { |
+ m_currentBacking.textureId = context()->createTexture(); |
+ m_currentBacking.size = viewportSize(); |
+ m_context->genMailboxCHROMIUM(m_currentBacking.mailbox.name); |
+ m_context->bindTexture(GL_TEXTURE_2D, m_currentBacking.textureId); |
+ m_context->texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
Sami
2013/01/25 23:17:27
Nit: could use texParameteri consistently.
no sievers
2013/02/06 23:36:00
Done.
|
+ m_context->texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
+ m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
+ m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
+ m_context->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
+ viewportSize().width(), viewportSize().height(), 0, |
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
+ } |
+ DCHECK(m_currentBacking.textureId); |
+ } |
+ } else { |
+ if (!m_isBackbufferDiscarded) |
+ return; |
- if (!m_capabilities.usingDiscardBackbuffer) |
- return; |
+ if (!m_capabilities.usingDiscardBackbuffer) |
+ return; |
- m_context->ensureBackbufferCHROMIUM(); |
+ m_context->ensureBackbufferCHROMIUM(); |
+ } |
m_isBackbufferDiscarded = false; |
} |
@@ -1499,7 +1614,17 @@ bool GLRenderer::useScopedTexture(DrawingFrame& frame, const ScopedResource* tex |
void GLRenderer::bindFramebufferToOutputSurface(DrawingFrame& frame) |
{ |
m_currentFramebufferLock.reset(); |
- GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0)); |
+ |
+ if (m_renderToMailbox) { |
+ ensureBackbuffer(); |
+ DCHECK(m_offscreenFramebufferId); |
+ DCHECK(m_currentBacking.textureId); |
+ GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, m_offscreenFramebufferId)); |
+ GLC(m_context, m_context->framebufferTexture2D( |
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_currentBacking.textureId, 0)); |
+ } else { |
+ GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0)); |
+ } |
} |
bool GLRenderer::bindFramebufferToTexture(DrawingFrame& frame, const ScopedResource* texture, const gfx::Rect& framebufferRect) |