Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/gpu/mailbox_output_surface.h" | 5 #include "content/renderer/gpu/mailbox_output_surface.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "cc/output/compositor_frame.h" | 8 #include "cc/output/compositor_frame.h" |
| 9 #include "cc/output/compositor_frame_ack.h" | 9 #include "cc/output/compositor_frame_ack.h" |
| 10 #include "cc/output/gl_frame_data.h" | 10 #include "cc/output/gl_frame_data.h" |
| 11 #include "cc/output/managed_memory_policy.h" | |
| 12 #include "cc/output/output_surface_client.h" | |
| 11 #include "cc/resources/resource_provider.h" | 13 #include "cc/resources/resource_provider.h" |
| 12 #include "content/renderer/gpu/frame_swap_message_queue.h" | 14 #include "content/renderer/gpu/frame_swap_message_queue.h" |
| 15 #include "gpu/command_buffer/client/context_support.h" | |
| 13 #include "gpu/command_buffer/client/gles2_interface.h" | 16 #include "gpu/command_buffer/client/gles2_interface.h" |
| 17 #include "gpu/command_buffer/common/gpu_memory_allocation.h" | |
| 14 #include "third_party/khronos/GLES2/gl2.h" | 18 #include "third_party/khronos/GLES2/gl2.h" |
| 15 #include "third_party/khronos/GLES2/gl2ext.h" | 19 #include "third_party/khronos/GLES2/gl2ext.h" |
| 16 | 20 |
| 17 using cc::CompositorFrame; | 21 using cc::CompositorFrame; |
| 18 using cc::GLFrameData; | 22 using cc::GLFrameData; |
| 19 using cc::ResourceProvider; | 23 using cc::ResourceProvider; |
| 20 using gpu::Mailbox; | 24 using gpu::Mailbox; |
| 21 using gpu::gles2::GLES2Interface; | 25 using gpu::gles2::GLES2Interface; |
| 22 | 26 |
| 23 namespace content { | 27 namespace content { |
| 24 | 28 |
| 25 MailboxOutputSurface::MailboxOutputSurface( | 29 MailboxOutputSurface::MailboxOutputSurface( |
| 26 int32_t routing_id, | |
| 27 uint32_t output_surface_id, | 30 uint32_t output_surface_id, |
| 28 const scoped_refptr<ContextProviderCommandBuffer>& context_provider, | 31 scoped_refptr<cc::ContextProvider> context_provider, |
| 29 const scoped_refptr<ContextProviderCommandBuffer>& worker_context_provider, | 32 scoped_refptr<cc::ContextProvider> worker_context_provider) |
| 30 scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue, | 33 : cc::OutputSurface(std::move(context_provider), |
| 31 cc::ResourceFormat format) | 34 std::move(worker_context_provider), |
| 32 : CompositorOutputSurface(routing_id, | 35 nullptr), |
| 33 output_surface_id, | 36 output_surface_id_(output_surface_id), |
| 34 context_provider, | |
| 35 worker_context_provider, | |
| 36 nullptr, | |
| 37 nullptr, | |
| 38 swap_frame_message_queue, | |
| 39 true), | |
| 40 fbo_(0), | 37 fbo_(0), |
| 41 is_backbuffer_discarded_(false), | 38 is_backbuffer_discarded_(false), |
| 42 format_(format) { | 39 weak_ptrs_(this) { |
| 43 pending_textures_.push_back(TransferableFrame()); | 40 pending_textures_.push_back(TransferableFrame()); |
| 44 capabilities_.uses_default_gl_framebuffer = false; | 41 capabilities_.uses_default_gl_framebuffer = false; |
| 45 } | 42 } |
| 46 | 43 |
| 47 MailboxOutputSurface::~MailboxOutputSurface() {} | 44 MailboxOutputSurface::~MailboxOutputSurface() = default; |
| 45 | |
| 46 bool MailboxOutputSurface::BindToClient(cc::OutputSurfaceClient* client) { | |
| 47 if (!cc::OutputSurface::BindToClient(client)) | |
| 48 return false; | |
| 49 | |
| 50 if (!context_provider()) { | |
| 51 // Without a GPU context, the memory policy otherwise wouldn't be set. | |
| 52 client->SetMemoryPolicy(cc::ManagedMemoryPolicy( | |
| 53 128 * 1024 * 1024, gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, | |
| 54 base::SharedMemory::GetHandleLimit() / 3)); | |
| 55 } | |
| 56 | |
| 57 return true; | |
| 58 } | |
| 48 | 59 |
| 49 void MailboxOutputSurface::DetachFromClient() { | 60 void MailboxOutputSurface::DetachFromClient() { |
| 50 DiscardBackbuffer(); | 61 DiscardBackbuffer(); |
| 51 while (!pending_textures_.empty()) { | 62 while (!pending_textures_.empty()) { |
| 52 if (pending_textures_.front().texture_id) { | 63 if (pending_textures_.front().texture_id) { |
| 53 context_provider_->ContextGL()->DeleteTextures( | 64 context_provider_->ContextGL()->DeleteTextures( |
| 54 1, &pending_textures_.front().texture_id); | 65 1, &pending_textures_.front().texture_id); |
| 55 } | 66 } |
| 56 pending_textures_.pop_front(); | 67 pending_textures_.pop_front(); |
| 57 } | 68 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 80 } | 91 } |
| 81 | 92 |
| 82 if (!current_backing_.texture_id) { | 93 if (!current_backing_.texture_id) { |
| 83 gl->GenTextures(1, ¤t_backing_.texture_id); | 94 gl->GenTextures(1, ¤t_backing_.texture_id); |
| 84 current_backing_.size = surface_size_; | 95 current_backing_.size = surface_size_; |
| 85 gl->BindTexture(GL_TEXTURE_2D, current_backing_.texture_id); | 96 gl->BindTexture(GL_TEXTURE_2D, current_backing_.texture_id); |
| 86 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 97 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 87 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 98 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 88 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 99 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 89 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 100 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 90 gl->TexImage2D(GL_TEXTURE_2D, | 101 gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(cc::RGBA_8888), |
| 91 0, | 102 surface_size_.width(), surface_size_.height(), 0, |
| 92 GLInternalFormat(format_), | 103 GLDataFormat(cc::RGBA_8888), GLDataType(cc::RGBA_8888), |
| 93 surface_size_.width(), | |
| 94 surface_size_.height(), | |
| 95 0, | |
| 96 GLDataFormat(format_), | |
| 97 GLDataType(format_), | |
| 98 NULL); | 104 NULL); |
| 99 gl->GenMailboxCHROMIUM(current_backing_.mailbox.name); | 105 gl->GenMailboxCHROMIUM(current_backing_.mailbox.name); |
| 100 gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, current_backing_.mailbox.name); | 106 gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, current_backing_.mailbox.name); |
| 101 } | 107 } |
| 102 } | 108 } |
| 103 } | 109 } |
| 104 | 110 |
| 105 void MailboxOutputSurface::DiscardBackbuffer() { | 111 void MailboxOutputSurface::DiscardBackbuffer() { |
| 106 is_backbuffer_discarded_ = true; | 112 is_backbuffer_discarded_ = true; |
| 107 | 113 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 GL_COLOR_ATTACHMENT0, | 156 GL_COLOR_ATTACHMENT0, |
| 151 GL_TEXTURE_2D, | 157 GL_TEXTURE_2D, |
| 152 current_backing_.texture_id, | 158 current_backing_.texture_id, |
| 153 0); | 159 0); |
| 154 } | 160 } |
| 155 | 161 |
| 156 void MailboxOutputSurface::OnSwapAck(uint32_t output_surface_id, | 162 void MailboxOutputSurface::OnSwapAck(uint32_t output_surface_id, |
| 157 const cc::CompositorFrameAck& ack) { | 163 const cc::CompositorFrameAck& ack) { |
| 158 // Ignore message if it's a stale one coming from a different output surface | 164 // Ignore message if it's a stale one coming from a different output surface |
| 159 // (e.g. after a lost context). | 165 // (e.g. after a lost context). |
| 160 if (output_surface_id != output_surface_id_) { | 166 if (output_surface_id != output_surface_id_) |
| 161 CompositorOutputSurface::OnSwapAck(output_surface_id, ack); | |
| 162 return; | 167 return; |
| 163 } | 168 |
| 164 if (!ack.gl_frame_data->mailbox.IsZero()) { | 169 if (!ack.gl_frame_data->mailbox.IsZero()) { |
| 165 DCHECK(!ack.gl_frame_data->size.IsEmpty()); | 170 DCHECK(!ack.gl_frame_data->size.IsEmpty()); |
| 166 // The browser could be returning the oldest or any other pending texture | 171 // The browser could be returning the oldest or any other pending texture |
| 167 // if it decided to skip a frame. | 172 // if it decided to skip a frame. |
| 168 std::deque<TransferableFrame>::iterator it; | 173 std::deque<TransferableFrame>::iterator it; |
| 169 for (it = pending_textures_.begin(); it != pending_textures_.end(); it++) { | 174 for (it = pending_textures_.begin(); it != pending_textures_.end(); it++) { |
| 170 DCHECK(!it->mailbox.IsZero()); | 175 DCHECK(!it->mailbox.IsZero()); |
| 171 if (!memcmp(it->mailbox.name, | 176 if (!memcmp(it->mailbox.name, |
| 172 ack.gl_frame_data->mailbox.name, | 177 ack.gl_frame_data->mailbox.name, |
| 173 sizeof(it->mailbox.name))) { | 178 sizeof(it->mailbox.name))) { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 188 } else { | 193 } else { |
| 189 DCHECK(!pending_textures_.empty()); | 194 DCHECK(!pending_textures_.empty()); |
| 190 // The browser always keeps one texture as the frontbuffer. | 195 // The browser always keeps one texture as the frontbuffer. |
| 191 // If it does not return a mailbox, it discarded the frontbuffer which is | 196 // If it does not return a mailbox, it discarded the frontbuffer which is |
| 192 // the oldest texture we sent. | 197 // the oldest texture we sent. |
| 193 uint32_t texture_id = pending_textures_.front().texture_id; | 198 uint32_t texture_id = pending_textures_.front().texture_id; |
| 194 if (texture_id) | 199 if (texture_id) |
| 195 context_provider_->ContextGL()->DeleteTextures(1, &texture_id); | 200 context_provider_->ContextGL()->DeleteTextures(1, &texture_id); |
| 196 pending_textures_.pop_front(); | 201 pending_textures_.pop_front(); |
| 197 } | 202 } |
| 198 CompositorOutputSurface::OnSwapAck(output_surface_id, ack); | 203 |
| 204 ReclaimResources(&ack); | |
| 205 client_->DidSwapBuffersComplete(); | |
| 206 } | |
| 207 | |
| 208 void MailboxOutputSurface::ShortcutSwapAck( | |
| 209 uint32_t output_surface_id, | |
| 210 std::unique_ptr<cc::GLFrameData> gl_frame_data) { | |
| 211 if (!previous_frame_ack_) { | |
| 212 previous_frame_ack_.reset(new cc::CompositorFrameAck); | |
| 213 previous_frame_ack_->gl_frame_data.reset(new cc::GLFrameData); | |
| 214 } | |
| 215 | |
| 216 OnSwapAck(output_surface_id, *previous_frame_ack_); | |
| 217 | |
| 218 previous_frame_ack_->gl_frame_data = std::move(gl_frame_data); | |
| 199 } | 219 } |
| 200 | 220 |
| 201 void MailboxOutputSurface::SwapBuffers(cc::CompositorFrame* frame) { | 221 void MailboxOutputSurface::SwapBuffers(cc::CompositorFrame* frame) { |
| 222 // This class is here to support layout tests that are currently | |
| 223 // doing a readback in the renderer instead of the browser. So they | |
| 224 // are using deprecated code paths in the renderer and don't need to | |
| 225 // actually swap anything to the browser. We shortcut the swap to the | |
| 226 // browser here and just ack directly within the renderer process. | |
| 227 // Once crbug.com/311404 is fixed, this can be removed. | |
| 228 | |
| 229 // This would indicate that crbug.com/311404 is being fixed, and this | |
| 230 // block needs to be removed. | |
| 231 DCHECK(!frame->delegated_frame_data); | |
| 232 | |
| 202 DCHECK(frame->gl_frame_data); | 233 DCHECK(frame->gl_frame_data); |
| 203 DCHECK(!surface_size_.IsEmpty()); | 234 DCHECK(!surface_size_.IsEmpty()); |
| 204 DCHECK(surface_size_ == current_backing_.size); | 235 DCHECK(surface_size_ == current_backing_.size); |
| 205 DCHECK(frame->gl_frame_data->size == current_backing_.size); | 236 DCHECK(frame->gl_frame_data->size == current_backing_.size); |
| 206 DCHECK(!current_backing_.mailbox.IsZero() || | 237 DCHECK(!current_backing_.mailbox.IsZero() || |
| 207 context_provider_->ContextGL()->GetGraphicsResetStatusKHR() != | 238 context_provider_->ContextGL()->GetGraphicsResetStatusKHR() != |
| 208 GL_NO_ERROR); | 239 GL_NO_ERROR); |
| 209 | 240 |
| 210 frame->gl_frame_data->mailbox = current_backing_.mailbox; | 241 frame->gl_frame_data->mailbox = current_backing_.mailbox; |
| 211 | 242 |
| 212 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 243 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
|
danakj
2016/05/24 20:54:32
But youd think if it was null, then calling Insert
| |
| 213 | 244 |
| 214 const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); | 245 const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); |
| 215 gl->Flush(); | 246 gl->Flush(); |
| 216 | |
| 217 gl->GenSyncTokenCHROMIUM(fence_sync, | 247 gl->GenSyncTokenCHROMIUM(fence_sync, |
| 218 frame->gl_frame_data->sync_token.GetData()); | 248 frame->gl_frame_data->sync_token.GetData()); |
| 219 | 249 |
| 220 CompositorOutputSurface::SwapBuffers(frame); | 250 context_provider()->ContextSupport()->SignalSyncToken( |
| 251 frame->gl_frame_data->sync_token, | |
| 252 base::Bind(&MailboxOutputSurface::ShortcutSwapAck, | |
| 253 weak_ptrs_.GetWeakPtr(), output_surface_id_, | |
| 254 base::Passed(&frame->gl_frame_data))); | |
|
danakj
2016/05/24 20:58:10
Ohh we're passing gl_frame_data here, but using it
| |
| 221 | 255 |
| 222 pending_textures_.push_back(current_backing_); | 256 pending_textures_.push_back(current_backing_); |
| 223 current_backing_ = TransferableFrame(); | 257 current_backing_ = TransferableFrame(); |
| 224 } | |
| 225 | 258 |
| 226 size_t MailboxOutputSurface::GetNumAcksPending() { | 259 client_->DidSwapBuffers(); |
| 227 DCHECK(pending_textures_.size()); | |
| 228 return pending_textures_.size() - 1; | |
| 229 } | 260 } |
| 230 | 261 |
| 231 MailboxOutputSurface::TransferableFrame::TransferableFrame() : texture_id(0) {} | 262 MailboxOutputSurface::TransferableFrame::TransferableFrame() : texture_id(0) {} |
| 232 | 263 |
| 233 MailboxOutputSurface::TransferableFrame::TransferableFrame( | 264 MailboxOutputSurface::TransferableFrame::TransferableFrame( |
| 234 uint32_t texture_id, | 265 uint32_t texture_id, |
| 235 const gpu::Mailbox& mailbox, | 266 const gpu::Mailbox& mailbox, |
| 236 const gfx::Size size) | 267 const gfx::Size size) |
| 237 : texture_id(texture_id), mailbox(mailbox), size(size) {} | 268 : texture_id(texture_id), mailbox(mailbox), size(size) {} |
| 238 | 269 |
| 239 } // namespace content | 270 } // namespace content |
| OLD | NEW |