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/common/gpu/texture_image_transport_surface.h" | 5 #include "content/common/gpu/texture_image_transport_surface.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "content/common/gpu/gl_scoped_binders.h" | 11 #include "content/common/gpu/gl_scoped_binders.h" |
| 12 #include "content/common/gpu/gpu_channel.h" | 12 #include "content/common/gpu/gpu_channel.h" |
| 13 #include "content/common/gpu/gpu_channel_manager.h" | 13 #include "content/common/gpu/gpu_channel_manager.h" |
| 14 #include "content/common/gpu/gpu_messages.h" | 14 #include "content/common/gpu/gpu_messages.h" |
| 15 #include "content/common/gpu/sync_point_manager.h" | 15 #include "content/common/gpu/sync_point_manager.h" |
| 16 #include "content/public/common/content_switches.h" | 16 #include "content/public/common/content_switches.h" |
| 17 #include "gpu/command_buffer/service/context_group.h" | 17 #include "gpu/command_buffer/service/context_group.h" |
| 18 #include "gpu/command_buffer/service/gpu_scheduler.h" | 18 #include "gpu/command_buffer/service/gpu_scheduler.h" |
| 19 #include "gpu/command_buffer/service/texture_manager.h" | 19 #include "gpu/command_buffer/service/texture_definition.h" |
| 20 | 20 |
| 21 using gpu::gles2::ContextGroup; | 21 using gpu::gles2::ContextGroup; |
| 22 using gpu::gles2::MailboxManager; | |
| 23 using gpu::gles2::MailboxName; | |
| 24 using gpu::gles2::TextureDefinition; | |
| 22 using gpu::gles2::TextureManager; | 25 using gpu::gles2::TextureManager; |
| 23 typedef TextureManager::TextureInfo TextureInfo; | |
| 24 | 26 |
| 25 namespace content { | 27 namespace content { |
| 26 | 28 |
| 27 TextureImageTransportSurface::Texture::Texture() | 29 TextureImageTransportSurface::Texture::Texture() |
| 28 : client_id(0), | 30 : service_id(0), |
| 29 sent_to_client(false) { | 31 identifier(0) { |
| 30 } | 32 } |
| 31 | 33 |
| 32 TextureImageTransportSurface::Texture::~Texture() { | 34 TextureImageTransportSurface::Texture::~Texture() { |
| 33 } | 35 } |
| 34 | 36 |
| 35 TextureImageTransportSurface::TextureImageTransportSurface( | 37 TextureImageTransportSurface::TextureImageTransportSurface( |
| 36 GpuChannelManager* manager, | 38 GpuChannelManager* manager, |
| 37 GpuCommandBufferStub* stub, | 39 GpuCommandBufferStub* stub, |
| 38 const gfx::GLSurfaceHandle& handle) | 40 const gfx::GLSurfaceHandle& handle) |
| 39 : fbo_id_(0), | 41 : fbo_id_(0), |
| 40 front_(0), | |
| 41 stub_destroyed_(false), | 42 stub_destroyed_(false), |
| 42 backbuffer_suggested_allocation_(true), | 43 backbuffer_suggested_allocation_(true), |
| 43 frontbuffer_suggested_allocation_(true), | 44 frontbuffer_suggested_allocation_(true), |
| 44 frontbuffer_is_protected_(true), | |
| 45 protection_state_id_(0), | |
| 46 handle_(handle), | 45 handle_(handle), |
| 47 parent_stub_(NULL), | |
| 48 is_swap_buffers_pending_(false), | 46 is_swap_buffers_pending_(false), |
| 49 did_unschedule_(false), | 47 did_unschedule_(false) { |
| 50 did_flip_(false) { | |
| 51 helper_.reset(new ImageTransportHelper(this, | 48 helper_.reset(new ImageTransportHelper(this, |
| 52 manager, | 49 manager, |
| 53 stub, | 50 stub, |
| 54 gfx::kNullPluginWindow)); | 51 gfx::kNullPluginWindow)); |
| 55 } | 52 } |
| 56 | 53 |
| 57 TextureImageTransportSurface::~TextureImageTransportSurface() { | 54 TextureImageTransportSurface::~TextureImageTransportSurface() { |
| 58 DCHECK(stub_destroyed_); | 55 DCHECK(stub_destroyed_); |
| 59 Destroy(); | 56 Destroy(); |
| 60 } | 57 } |
| 61 | 58 |
| 62 bool TextureImageTransportSurface::Initialize() { | 59 bool TextureImageTransportSurface::Initialize() { |
| 60 mailbox_manager_ = | |
| 61 helper_->stub()->decoder()->GetContextGroup()->mailbox_manager(); | |
| 62 | |
| 63 backbuffer_.identifier = 1; | |
| 64 | |
| 63 GpuChannelManager* manager = helper_->manager(); | 65 GpuChannelManager* manager = helper_->manager(); |
| 64 GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id); | |
| 65 if (!parent_channel) | |
| 66 return false; | |
| 67 | |
| 68 parent_stub_ = parent_channel->LookupCommandBuffer(handle_.parent_context_id); | |
| 69 if (!parent_stub_) | |
| 70 return false; | |
| 71 | |
| 72 parent_stub_->AddDestructionObserver(this); | |
| 73 TextureManager* texture_manager = | |
| 74 parent_stub_->decoder()->GetContextGroup()->texture_manager(); | |
| 75 DCHECK(texture_manager); | |
| 76 | |
| 77 for (int i = 0; i < 2; ++i) { | |
| 78 Texture& texture = textures_[i]; | |
| 79 texture.client_id = handle_.parent_texture_id[i]; | |
| 80 texture.info = texture_manager->GetTextureInfo(texture.client_id); | |
| 81 if (!texture.info) | |
| 82 return false; | |
| 83 | |
| 84 if (!texture.info->target()) | |
| 85 texture_manager->SetInfoTarget(texture.info, GL_TEXTURE_2D); | |
| 86 texture_manager->SetParameter( | |
| 87 texture.info, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 88 texture_manager->SetParameter( | |
| 89 texture.info, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 90 texture_manager->SetParameter( | |
| 91 texture.info, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 92 texture_manager->SetParameter( | |
| 93 texture.info, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 94 } | |
| 95 | |
| 96 surface_ = manager->GetDefaultOffscreenSurface(); | 66 surface_ = manager->GetDefaultOffscreenSurface(); |
| 97 if (!surface_.get()) | 67 if (!surface_.get()) |
| 98 return false; | 68 return false; |
| 99 | 69 |
| 100 if (!helper_->Initialize()) | 70 if (!helper_->Initialize()) |
| 101 return false; | 71 return false; |
| 102 | 72 |
| 103 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 73 GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id); |
| 104 if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess)) | 74 if (parent_channel) { |
| 105 helper_->SetPreemptByCounter(parent_channel->MessagesPendingCount()); | 75 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 76 if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess)) | |
| 77 helper_->SetPreemptByCounter(parent_channel->MessagesPendingCount()); | |
| 78 } | |
| 106 | 79 |
| 107 return true; | 80 return true; |
| 108 } | 81 } |
| 109 | 82 |
| 110 void TextureImageTransportSurface::Destroy() { | 83 void TextureImageTransportSurface::Destroy() { |
| 111 if (parent_stub_) { | 84 if (!stub_destroyed_) { |
| 112 parent_stub_->decoder()->MakeCurrent(); | 85 GpuHostMsg_AcceleratedSurfaceRelease_Params params; |
| 113 ReleaseParentStub(); | 86 helper_->SendAcceleratedSurfaceRelease(params); |
| 114 } | 87 } |
| 115 | 88 |
| 116 if (surface_.get()) | 89 if (surface_.get()) |
| 117 surface_ = NULL; | 90 surface_ = NULL; |
| 118 | 91 |
| 119 helper_->Destroy(); | 92 helper_->Destroy(); |
| 120 } | 93 } |
| 121 | 94 |
| 122 bool TextureImageTransportSurface::DeferDraws() { | 95 bool TextureImageTransportSurface::DeferDraws() { |
| 123 // The command buffer hit a draw/clear command that could clobber the | 96 // The command buffer hit a draw/clear command that could clobber the |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 142 } | 115 } |
| 143 | 116 |
| 144 bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { | 117 bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { |
| 145 if (stub_destroyed_) { | 118 if (stub_destroyed_) { |
| 146 // Early-exit so that we don't recreate the fbo. We still want to return | 119 // Early-exit so that we don't recreate the fbo. We still want to return |
| 147 // true, so that the context is made current and the GLES2DecoderImpl can | 120 // true, so that the context is made current and the GLES2DecoderImpl can |
| 148 // release its own resources. | 121 // release its own resources. |
| 149 return true; | 122 return true; |
| 150 } | 123 } |
| 151 | 124 |
| 125 if (!context_.get()) | |
| 126 context_ = helper_->stub()->decoder()->GetGLContext(); | |
| 127 | |
| 152 if (!fbo_id_) { | 128 if (!fbo_id_) { |
| 153 glGenFramebuffersEXT(1, &fbo_id_); | 129 glGenFramebuffersEXT(1, &fbo_id_); |
| 154 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); | 130 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); |
| 155 CreateBackTexture(gfx::Size(1, 1)); | 131 current_size_ = gfx::Size(1, 1); |
| 132 DCHECK(helper_->stub()); | |
|
jonathan.backer
2012/11/20 21:21:11
Seems a little late for this. Probably would have
| |
| 133 helper_->stub()->AddDestructionObserver(this); | |
| 134 } | |
| 135 | |
| 136 if (!backbuffer_.service_id) { | |
| 137 CreateBackTexture(); | |
| 156 | 138 |
| 157 #ifndef NDEBUG | 139 #ifndef NDEBUG |
| 158 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 140 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
| 159 if (status != GL_FRAMEBUFFER_COMPLETE) { | 141 if (status != GL_FRAMEBUFFER_COMPLETE) { |
| 160 DLOG(ERROR) << "Framebuffer incomplete."; | 142 DLOG(ERROR) << "Framebuffer incomplete."; |
| 161 glDeleteFramebuffersEXT(1, &fbo_id_); | 143 glDeleteFramebuffersEXT(1, &fbo_id_); |
| 162 fbo_id_ = 0; | 144 fbo_id_ = 0; |
| 163 return false; | 145 return false; |
| 164 } | 146 } |
| 165 #endif | 147 #endif |
| 166 DCHECK(helper_->stub()); | |
| 167 helper_->stub()->AddDestructionObserver(this); | |
| 168 } | 148 } |
| 169 | |
| 170 return true; | 149 return true; |
| 171 } | 150 } |
| 172 | 151 |
| 173 unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() { | 152 unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() { |
| 174 return fbo_id_; | 153 return fbo_id_; |
| 175 } | 154 } |
| 176 | 155 |
| 177 void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { | 156 void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { |
| 178 if (backbuffer_suggested_allocation_ == allocation) | 157 if (backbuffer_suggested_allocation_ == allocation) |
| 179 return; | 158 return; |
| 180 backbuffer_suggested_allocation_ = allocation; | 159 backbuffer_suggested_allocation_ = allocation; |
| 181 | 160 |
| 182 if (!helper_->MakeCurrent()) | 161 // For |allocation| == true, we have to be careful as there might still be |
| 183 return; | 162 // a swap ACK pending. Either way, we will either retrieve the texture when |
|
piman
2012/11/29 04:31:11
note: with https://codereview.chromium.org/1131623
no sievers
2012/11/29 19:57:00
We could allocate it now if allocation == true, or
| |
| 184 | 163 // the ACK is handled, or allocate a new one when being made current again. |
| 185 if (backbuffer_suggested_allocation_) { | 164 if (!backbuffer_suggested_allocation_ && helper_->MakeCurrent()) |
| 186 DCHECK(!textures_[back()].info->service_id() || | 165 ReleaseBackBuffer(); |
| 187 !textures_[back()].sent_to_client); | |
| 188 CreateBackTexture(textures_[back()].size); | |
| 189 } else { | |
| 190 ReleaseTexture(back()); | |
| 191 } | |
| 192 } | 166 } |
| 193 | 167 |
| 194 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { | 168 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { |
| 195 if (frontbuffer_suggested_allocation_ == allocation) | 169 if (frontbuffer_suggested_allocation_ == allocation) |
| 196 return; | 170 return; |
| 197 frontbuffer_suggested_allocation_ = allocation; | 171 frontbuffer_suggested_allocation_ = allocation; |
| 198 AdjustFrontBufferAllocation(); | 172 AdjustFrontBufferAllocation(); |
| 199 } | 173 } |
| 200 | 174 |
| 201 void TextureImageTransportSurface::AdjustFrontBufferAllocation() { | 175 void TextureImageTransportSurface::AdjustFrontBufferAllocation() { |
| 202 if (!helper_->MakeCurrent()) | 176 if (!frontbuffer_suggested_allocation_) { |
| 203 return; | 177 GpuHostMsg_AcceleratedSurfaceRelease_Params params; |
| 204 | 178 helper_->SendAcceleratedSurfaceRelease(params); |
| 205 if (!frontbuffer_suggested_allocation_ && !frontbuffer_is_protected_ && | |
| 206 textures_[front()].info->service_id()) { | |
| 207 ReleaseTexture(front()); | |
| 208 if (textures_[front()].sent_to_client) { | |
| 209 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | |
| 210 params.identifier = textures_[front()].client_id; | |
| 211 helper_->SendAcceleratedSurfaceRelease(params); | |
| 212 textures_[front()].sent_to_client = false; | |
| 213 } | |
| 214 } | 179 } |
| 215 } | 180 } |
| 216 | 181 |
| 217 void* TextureImageTransportSurface::GetShareHandle() { | 182 void* TextureImageTransportSurface::GetShareHandle() { |
| 218 return GetHandle(); | 183 return GetHandle(); |
| 219 } | 184 } |
| 220 | 185 |
| 221 void* TextureImageTransportSurface::GetDisplay() { | 186 void* TextureImageTransportSurface::GetDisplay() { |
| 222 return surface_.get() ? surface_->GetDisplay() : NULL; | 187 return surface_.get() ? surface_->GetDisplay() : NULL; |
| 223 } | 188 } |
| 224 | 189 |
| 225 void* TextureImageTransportSurface::GetConfig() { | 190 void* TextureImageTransportSurface::GetConfig() { |
| 226 return surface_.get() ? surface_->GetConfig() : NULL; | 191 return surface_.get() ? surface_->GetConfig() : NULL; |
| 227 } | 192 } |
| 228 | 193 |
| 229 void TextureImageTransportSurface::OnResize(gfx::Size size) { | 194 void TextureImageTransportSurface::OnResize(gfx::Size size) { |
| 230 CreateBackTexture(size); | 195 current_size_ = size; |
| 196 CreateBackTexture(); | |
| 231 } | 197 } |
| 232 | 198 |
| 233 void TextureImageTransportSurface::OnWillDestroyStub( | 199 void TextureImageTransportSurface::OnWillDestroyStub( |
| 234 GpuCommandBufferStub* stub) { | 200 GpuCommandBufferStub* stub) { |
| 235 if (stub == parent_stub_) { | 201 DCHECK(stub == helper_->stub()); |
| 236 ReleaseParentStub(); | 202 stub->RemoveDestructionObserver(this); |
| 237 helper_->SetPreemptByCounter(NULL); | |
| 238 } else { | |
| 239 DCHECK(stub == helper_->stub()); | |
| 240 stub->RemoveDestructionObserver(this); | |
| 241 | 203 |
| 242 // We are losing the stub owning us, this is our last chance to clean up the | 204 // We are losing the stub owning us, this is our last chance to clean up the |
| 243 // resources we allocated in the stub's context. | 205 // resources we allocated in the stub's context. |
| 244 if (fbo_id_) { | 206 if (fbo_id_) { |
| 245 glDeleteFramebuffersEXT(1, &fbo_id_); | 207 glDeleteFramebuffersEXT(1, &fbo_id_); |
| 246 CHECK_GL_ERROR(); | 208 CHECK_GL_ERROR(); |
| 247 fbo_id_ = 0; | 209 fbo_id_ = 0; |
| 248 } | 210 } |
| 249 | 211 |
| 250 stub_destroyed_ = true; | 212 stub_destroyed_ = true; |
| 251 } | |
| 252 } | 213 } |
| 253 | 214 |
| 254 bool TextureImageTransportSurface::SwapBuffers() { | 215 bool TextureImageTransportSurface::SwapBuffers() { |
| 255 DCHECK(backbuffer_suggested_allocation_); | 216 DCHECK(backbuffer_suggested_allocation_); |
| 256 if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) | 217 if (!frontbuffer_suggested_allocation_) |
| 257 return true; | 218 return true; |
| 258 if (!parent_stub_) { | |
| 259 LOG(ERROR) << "SwapBuffers failed because no parent stub."; | |
| 260 return false; | |
| 261 } | |
| 262 | 219 |
| 263 glFlush(); | 220 glFlush(); |
| 264 front_ = back(); | 221 const uint64 identifier = backbuffer_.identifier; |
| 265 previous_damage_rect_ = gfx::Rect(textures_[front()].size); | 222 ProduceTexture(backbuffer_); |
| 266 | 223 |
| 267 DCHECK(textures_[front()].client_id != 0); | 224 // Do not allow destruction while we are still waiting for a swap ACK, |
| 225 // so we do not leak a texture in the mailbox. | |
| 226 AddRef(); | |
| 268 | 227 |
| 269 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 228 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
| 270 params.surface_handle = textures_[front()].client_id; | 229 params.surface_handle = identifier; |
| 271 params.size = textures_[front()].size; | 230 params.size = current_size_; |
| 272 params.protection_state_id = protection_state_id_; | |
| 273 params.skip_ack = false; | |
| 274 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | 231 helper_->SendAcceleratedSurfaceBuffersSwapped(params); |
| 275 | 232 |
| 276 DCHECK(!is_swap_buffers_pending_); | 233 DCHECK(!is_swap_buffers_pending_); |
| 277 is_swap_buffers_pending_ = true; | 234 is_swap_buffers_pending_ = true; |
| 278 return true; | 235 return true; |
| 279 } | 236 } |
| 280 | 237 |
| 281 bool TextureImageTransportSurface::PostSubBuffer( | 238 bool TextureImageTransportSurface::PostSubBuffer( |
| 282 int x, int y, int width, int height) { | 239 int x, int y, int width, int height) { |
| 283 DCHECK(backbuffer_suggested_allocation_); | 240 DCHECK(backbuffer_suggested_allocation_); |
| 284 DCHECK(textures_[back()].info->service_id()); | 241 DCHECK(backbuffer_.service_id); |
| 285 if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) | 242 if (!frontbuffer_suggested_allocation_) |
| 286 return true; | 243 return true; |
| 287 // If we are recreating the frontbuffer with this swap, make sure we are | |
| 288 // drawing a full frame. | |
| 289 DCHECK(textures_[front()].info->service_id() || | |
| 290 (!x && !y && gfx::Size(width, height) == textures_[back()].size)); | |
| 291 if (!parent_stub_) { | |
| 292 LOG(ERROR) << "PostSubBuffer failed because no parent stub."; | |
| 293 return false; | |
| 294 } | |
| 295 | |
| 296 const gfx::Rect new_damage_rect(x, y, width, height); | 244 const gfx::Rect new_damage_rect(x, y, width, height); |
| 245 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); | |
| 297 | 246 |
| 298 // An empty damage rect is a successful no-op. | 247 // An empty damage rect is a successful no-op. |
| 299 if (new_damage_rect.IsEmpty()) | 248 if (new_damage_rect.IsEmpty()) |
| 300 return true; | 249 return true; |
| 301 | 250 |
| 302 int back_texture_service_id = textures_[back()].info->service_id(); | 251 glFlush(); |
| 303 int front_texture_service_id = textures_[front()].info->service_id(); | 252 const uint64 identifier = backbuffer_.identifier; |
| 253 ProduceTexture(backbuffer_); | |
| 304 | 254 |
| 305 gfx::Size expected_size = textures_[back()].size; | 255 // Do not allow destruction while we are still waiting for a swap ACK, |
| 306 bool surfaces_same_size = textures_[front()].size == expected_size; | 256 // so we do not leak a texture in the mailbox. |
| 307 | 257 AddRef(); |
| 308 if (surfaces_same_size) { | |
| 309 std::vector<gfx::Rect> regions_to_copy; | |
| 310 GetRegionsToCopy(previous_damage_rect_, new_damage_rect, ®ions_to_copy); | |
| 311 | |
| 312 ScopedFrameBufferBinder fbo_binder(fbo_id_); | |
| 313 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | |
| 314 GL_COLOR_ATTACHMENT0, | |
| 315 GL_TEXTURE_2D, | |
| 316 front_texture_service_id, | |
| 317 0); | |
| 318 ScopedTextureBinder texture_binder(back_texture_service_id); | |
| 319 | |
| 320 for (size_t i = 0; i < regions_to_copy.size(); ++i) { | |
| 321 const gfx::Rect& region_to_copy = regions_to_copy[i]; | |
| 322 if (!region_to_copy.IsEmpty()) { | |
| 323 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, region_to_copy.x(), | |
| 324 region_to_copy.y(), region_to_copy.x(), region_to_copy.y(), | |
| 325 region_to_copy.width(), region_to_copy.height()); | |
| 326 } | |
| 327 } | |
| 328 } else if (!surfaces_same_size && did_flip_) { | |
| 329 DCHECK(new_damage_rect == gfx::Rect(expected_size)); | |
| 330 } | |
| 331 | |
| 332 glFlush(); | |
| 333 front_ = back(); | |
| 334 previous_damage_rect_ = new_damage_rect; | |
| 335 | |
| 336 DCHECK(textures_[front()].client_id); | |
| 337 | 258 |
| 338 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; | 259 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; |
| 339 params.surface_handle = textures_[front()].client_id; | 260 params.surface_handle = identifier; |
| 340 params.surface_size = textures_[front()].size; | 261 params.surface_size = current_size_; |
| 341 params.x = x; | 262 params.x = x; |
| 342 params.y = y; | 263 params.y = y; |
| 343 params.width = width; | 264 params.width = width; |
| 344 params.height = height; | 265 params.height = height; |
| 345 params.protection_state_id = protection_state_id_; | |
| 346 helper_->SendAcceleratedSurfacePostSubBuffer(params); | 266 helper_->SendAcceleratedSurfacePostSubBuffer(params); |
| 347 | 267 |
| 348 DCHECK(!is_swap_buffers_pending_); | 268 DCHECK(!is_swap_buffers_pending_); |
| 349 is_swap_buffers_pending_ = true; | 269 is_swap_buffers_pending_ = true; |
| 350 return true; | 270 return true; |
| 351 } | 271 } |
| 352 | 272 |
| 353 std::string TextureImageTransportSurface::GetExtensions() { | 273 std::string TextureImageTransportSurface::GetExtensions() { |
| 354 std::string extensions = gfx::GLSurface::GetExtensions(); | 274 std::string extensions = gfx::GLSurface::GetExtensions(); |
| 355 extensions += extensions.empty() ? "" : " "; | 275 extensions += extensions.empty() ? "" : " "; |
| 356 extensions += "GL_CHROMIUM_front_buffer_cached "; | 276 extensions += "GL_CHROMIUM_front_buffer_cached "; |
| 357 extensions += "GL_CHROMIUM_post_sub_buffer"; | 277 extensions += "GL_CHROMIUM_post_sub_buffer"; |
| 358 return extensions; | 278 return extensions; |
| 359 } | 279 } |
| 360 | 280 |
| 361 gfx::Size TextureImageTransportSurface::GetSize() { | 281 gfx::Size TextureImageTransportSurface::GetSize() { |
| 362 gfx::Size size = textures_[back()].size; | 282 gfx::Size size = current_size_; |
| 363 | 283 |
| 364 // OSMesa expects a non-zero size. | 284 // OSMesa expects a non-zero size. |
| 365 return gfx::Size(size.width() == 0 ? 1 : size.width(), | 285 return gfx::Size(size.width() == 0 ? 1 : size.width(), |
| 366 size.height() == 0 ? 1 : size.height()); | 286 size.height() == 0 ? 1 : size.height()); |
| 367 } | 287 } |
| 368 | 288 |
| 369 void* TextureImageTransportSurface::GetHandle() { | 289 void* TextureImageTransportSurface::GetHandle() { |
| 370 return surface_.get() ? surface_->GetHandle() : NULL; | 290 return surface_.get() ? surface_->GetHandle() : NULL; |
| 371 } | 291 } |
| 372 | 292 |
| 373 unsigned TextureImageTransportSurface::GetFormat() { | 293 unsigned TextureImageTransportSurface::GetFormat() { |
| 374 return surface_.get() ? surface_->GetFormat() : 0; | 294 return surface_.get() ? surface_->GetFormat() : 0; |
| 375 } | 295 } |
| 376 | 296 |
| 377 void TextureImageTransportSurface::OnSetFrontSurfaceIsProtected( | 297 void TextureImageTransportSurface::OnBufferPresented(uint64 surface_handle, |
| 378 bool is_protected, uint32 protection_state_id) { | |
| 379 protection_state_id_ = protection_state_id; | |
| 380 if (frontbuffer_is_protected_ == is_protected) | |
| 381 return; | |
| 382 frontbuffer_is_protected_ = is_protected; | |
| 383 AdjustFrontBufferAllocation(); | |
| 384 | |
| 385 // If surface is set to protected, and we haven't actually released it yet, | |
| 386 // we can set the ui surface handle now just by sending a swap message. | |
| 387 if (is_protected && textures_[front()].info->service_id() && | |
| 388 textures_[front()].sent_to_client) { | |
| 389 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | |
| 390 params.surface_handle = textures_[front()].client_id; | |
| 391 params.size = textures_[front()].size; | |
| 392 params.protection_state_id = protection_state_id_; | |
| 393 params.skip_ack = true; | |
| 394 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | |
| 395 } | |
| 396 } | |
| 397 | |
| 398 void TextureImageTransportSurface::OnBufferPresented(bool presented, | |
| 399 uint32 sync_point) { | 298 uint32 sync_point) { |
| 400 if (sync_point == 0) { | 299 if (sync_point == 0) { |
| 401 BufferPresentedImpl(presented); | 300 BufferPresentedImpl(surface_handle); |
| 402 } else { | 301 } else { |
| 403 helper_->manager()->sync_point_manager()->AddSyncPointCallback( | 302 helper_->manager()->sync_point_manager()->AddSyncPointCallback( |
| 404 sync_point, | 303 sync_point, |
| 405 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, | 304 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, |
| 406 this->AsWeakPtr(), | 305 this, |
| 407 presented)); | 306 surface_handle)); |
| 408 } | 307 } |
| 308 | |
| 309 // Careful, we might get deleted now if we were only waiting for | |
| 310 // a final swap ACK. | |
| 311 Release(); | |
|
jonathan.backer
2012/11/20 21:21:11
Hmm... do we want |BufferPresentedImpl| to do the
piman
2012/11/29 04:31:11
This looks fine, in the first case (sync_point==0)
| |
| 409 } | 312 } |
| 410 | 313 |
| 411 void TextureImageTransportSurface::BufferPresentedImpl(bool presented) { | 314 void TextureImageTransportSurface::BufferPresentedImpl(uint64 surface_handle) { |
| 315 DCHECK(!backbuffer_.service_id); | |
| 316 if (surface_handle) { | |
| 317 backbuffer_.identifier = surface_handle; | |
|
piman
2012/11/30 03:54:32
nit: DCHECK it's 1 or 2?
| |
| 318 ConsumeTexture(backbuffer_); | |
| 319 } else { | |
| 320 // We didn't get back a texture, so allocate 'the other' buffer. | |
| 321 backbuffer_.identifier = (backbuffer_.identifier == 1) ? 2 : 1; | |
| 322 } | |
| 323 | |
| 324 if (stub_destroyed_ && backbuffer_.service_id) { | |
| 325 // TODO(sievers): Remove this after changes to the mailbox to take ownership | |
| 326 // of the service ids. | |
| 327 DCHECK(context_.get() && surface_.get()); | |
| 328 if (context_->MakeCurrent(surface_.get())) | |
| 329 glDeleteTextures(1, &backbuffer_.service_id); | |
|
piman
2012/11/30 03:54:32
nit: indent
| |
| 330 | |
| 331 return; | |
| 332 } | |
| 333 | |
| 412 DCHECK(is_swap_buffers_pending_); | 334 DCHECK(is_swap_buffers_pending_); |
| 413 is_swap_buffers_pending_ = false; | 335 is_swap_buffers_pending_ = false; |
| 414 | 336 |
| 415 if (presented) { | |
| 416 // If we had not flipped, the two frame damage tracking is inconsistent. | |
| 417 // So conservatively take the whole frame. | |
| 418 if (!did_flip_) | |
| 419 previous_damage_rect_ = gfx::Rect(textures_[front()].size); | |
| 420 } else { | |
| 421 front_ = back(); | |
| 422 previous_damage_rect_ = gfx::Rect(0, 0, 0, 0); | |
| 423 } | |
| 424 | |
| 425 did_flip_ = presented; | |
| 426 | |
| 427 // We're relying on the fact that the parent context is | 337 // We're relying on the fact that the parent context is |
| 428 // finished with it's context when it inserts the sync point that | 338 // finished with it's context when it inserts the sync point that |
| 429 // triggers this callback. | 339 // triggers this callback. |
| 430 if (helper_->MakeCurrent()) { | 340 if (helper_->MakeCurrent()) { |
| 431 if (textures_[front()].size != textures_[back()].size || | 341 if (!backbuffer_suggested_allocation_) |
| 432 !textures_[back()].info->service_id() || | 342 ReleaseBackBuffer(); |
| 433 !textures_[back()].sent_to_client) { | 343 else if (backbuffer_.size != current_size_ || !backbuffer_.service_id) |
| 434 // We may get an ACK from a stale swap just to reschedule. In that case, | 344 CreateBackTexture(); |
|
piman
2012/11/30 03:54:32
If we're going to recreate the backbuffer lazily i
| |
| 435 // we may not have a backbuffer suggestion and should not recreate one. | 345 else |
| 436 if (backbuffer_suggested_allocation_) | |
| 437 CreateBackTexture(textures_[front()].size); | |
| 438 } else { | |
| 439 AttachBackTextureToFBO(); | 346 AttachBackTextureToFBO(); |
| 440 } | |
| 441 } | 347 } |
| 442 | 348 |
| 443 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context | 349 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context |
| 444 // logic. | 350 // logic. |
| 445 if (did_unschedule_) { | 351 if (did_unschedule_) { |
| 446 did_unschedule_ = false; | 352 did_unschedule_ = false; |
| 447 helper_->SetScheduled(true); | 353 helper_->SetScheduled(true); |
| 448 } | 354 } |
| 449 } | 355 } |
| 450 | 356 |
| 451 void TextureImageTransportSurface::OnResizeViewACK() { | 357 void TextureImageTransportSurface::OnResizeViewACK() { |
| 452 NOTREACHED(); | 358 NOTREACHED(); |
| 453 } | 359 } |
| 454 | 360 |
| 455 void TextureImageTransportSurface::ReleaseTexture(int id) { | 361 void TextureImageTransportSurface::ReleaseBackBuffer() { |
| 456 if (!parent_stub_) | 362 if (!backbuffer_.service_id) |
| 457 return; | 363 return; |
| 458 Texture& texture = textures_[id]; | |
| 459 TextureInfo* info = texture.info; | |
| 460 DCHECK(info); | |
| 461 | 364 |
| 462 GLuint service_id = info->service_id(); | 365 glDeleteTextures(1, &backbuffer_.service_id); |
| 463 if (!service_id) | 366 backbuffer_.service_id = 0; |
| 464 return; | |
| 465 info->SetServiceId(0); | |
| 466 | |
| 467 { | |
| 468 ScopedFrameBufferBinder fbo_binder(fbo_id_); | |
| 469 glDeleteTextures(1, &service_id); | |
| 470 } | |
| 471 glFlush(); | 367 glFlush(); |
| 472 CHECK_GL_ERROR(); | 368 CHECK_GL_ERROR(); |
| 473 } | 369 } |
| 474 | 370 |
| 475 void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { | 371 void TextureImageTransportSurface::CreateBackTexture() { |
| 476 if (!parent_stub_) | 372 // If |is_swap_buffers_pending| we are waiting for our backbuffer |
| 477 return; | 373 // in the mailbox, so we shouldn't be reallocating it now. |
| 478 Texture& texture = textures_[back()]; | 374 // The deferred scheduling logic guarantees that the context would |
| 479 TextureInfo* info = texture.info; | 375 // only be made current here for non-drawing GL commands, so it's |
| 480 DCHECK(info); | 376 // safe to bail out. |
| 481 | 377 if (is_swap_buffers_pending_) |
|
jonathan.backer
2012/11/20 21:21:11
I'm confused (you may have addressed this before),
piman
2012/11/29 04:31:11
I think with https://codereview.chromium.org/11316
no sievers
2012/11/29 19:57:00
We could still get non-drawing GL commands, right?
piman
2012/11/30 03:54:32
So, yes, we may run some GL commands, which will c
| |
| 482 GLuint service_id = info->service_id(); | |
| 483 | |
| 484 if (service_id && texture.size == size && texture.sent_to_client) | |
| 485 return; | 378 return; |
| 486 | 379 |
| 487 if (!service_id) { | 380 if (backbuffer_.service_id && backbuffer_.size == current_size_) |
| 488 glGenTextures(1, &service_id); | 381 return; |
| 489 info->SetServiceId(service_id); | 382 |
| 383 DCHECK(!backbuffer_.service_id || mailbox_names_.count( | |
| 384 backbuffer_.identifier)); | |
|
jonathan.backer
2012/11/20 21:21:11
nit: indentation
| |
| 385 if (!backbuffer_.service_id) { | |
| 386 MailboxName new_mailbox_name; | |
| 387 mailbox_manager_->GenerateMailboxName(&new_mailbox_name); | |
| 388 mailbox_names_[backbuffer_.identifier] = new_mailbox_name; | |
|
piman
2012/11/30 03:54:32
Should we check that the mailbox_names_ slot is em
no sievers
2012/12/01 00:58:38
We do replace the entry though when we reallocate
piman
2012/12/03 21:08:43
Why? resize shouldn't cause us to gen a new textur
no sievers
2012/12/03 23:20:38
Done.
| |
| 389 glGenTextures(1, &backbuffer_.service_id); | |
| 490 } | 390 } |
| 491 | 391 |
| 492 if (size != texture.size) { | 392 backbuffer_.size = current_size_; |
| 493 texture.size = size; | |
| 494 TextureManager* texture_manager = | |
| 495 parent_stub_->decoder()->GetContextGroup()->texture_manager(); | |
| 496 texture_manager->SetLevelInfo( | |
| 497 info, | |
| 498 GL_TEXTURE_2D, | |
| 499 0, | |
| 500 GL_RGBA, | |
| 501 size.width(), | |
| 502 size.height(), | |
| 503 1, | |
| 504 0, | |
| 505 GL_RGBA, | |
| 506 GL_UNSIGNED_BYTE, | |
| 507 true); | |
| 508 } | |
| 509 | 393 |
| 510 { | 394 { |
| 511 ScopedTextureBinder texture_binder(service_id); | 395 ScopedTextureBinder texture_binder(backbuffer_.service_id); |
| 512 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 396 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 513 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 397 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 514 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 515 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 399 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 516 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | 400 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
| 517 size.width(), size.height(), 0, | 401 current_size_.width(), current_size_.height(), 0, |
| 518 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 402 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| 519 CHECK_GL_ERROR(); | 403 CHECK_GL_ERROR(); |
| 520 } | 404 } |
| 521 | 405 |
| 522 AttachBackTextureToFBO(); | 406 AttachBackTextureToFBO(); |
| 523 | 407 |
| 408 const MailboxName& mailbox_name = mailbox_names_[backbuffer_.identifier]; | |
| 409 | |
| 524 GpuHostMsg_AcceleratedSurfaceNew_Params params; | 410 GpuHostMsg_AcceleratedSurfaceNew_Params params; |
| 525 params.width = size.width(); | 411 params.width = current_size_.width(); |
| 526 params.height = size.height(); | 412 params.height = current_size_.height(); |
| 527 params.surface_handle = texture.client_id; | 413 params.surface_handle = backbuffer_.identifier; |
| 414 params.mailbox_name.append((char*)&mailbox_name, sizeof(mailbox_name)); | |
|
piman
2012/11/30 03:54:32
nit: no c-style cast (use reinterpret_cast).
| |
| 528 helper_->SendAcceleratedSurfaceNew(params); | 415 helper_->SendAcceleratedSurfaceNew(params); |
| 529 texture.sent_to_client = true; | |
| 530 } | 416 } |
| 531 | 417 |
| 532 void TextureImageTransportSurface::AttachBackTextureToFBO() { | 418 void TextureImageTransportSurface::AttachBackTextureToFBO() { |
| 533 if (!parent_stub_) | 419 DCHECK(backbuffer_.service_id); |
| 534 return; | |
| 535 TextureInfo* info = textures_[back()].info; | |
| 536 DCHECK(info); | |
| 537 | |
| 538 ScopedFrameBufferBinder fbo_binder(fbo_id_); | 420 ScopedFrameBufferBinder fbo_binder(fbo_id_); |
| 539 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | 421 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
| 540 GL_COLOR_ATTACHMENT0, | 422 GL_COLOR_ATTACHMENT0, |
| 541 GL_TEXTURE_2D, | 423 GL_TEXTURE_2D, |
| 542 info->service_id(), | 424 backbuffer_.service_id, |
| 543 0); | 425 0); |
| 544 glFlush(); | 426 glFlush(); |
| 545 CHECK_GL_ERROR(); | 427 CHECK_GL_ERROR(); |
| 546 | 428 |
| 547 #ifndef NDEBUG | 429 #ifndef NDEBUG |
| 548 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 430 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
| 549 if (status != GL_FRAMEBUFFER_COMPLETE) { | 431 if (status != GL_FRAMEBUFFER_COMPLETE) { |
| 550 DLOG(ERROR) << "Framebuffer incomplete."; | 432 DLOG(FATAL) << "Framebuffer incomplete: " << status; |
| 551 } | 433 } |
| 552 #endif | 434 #endif |
| 553 } | 435 } |
| 554 | 436 |
| 555 void TextureImageTransportSurface::ReleaseParentStub() { | 437 void TextureImageTransportSurface::ConsumeTexture(Texture& texture) { |
| 556 DCHECK(parent_stub_); | 438 DCHECK(!texture.service_id); |
| 557 parent_stub_->RemoveDestructionObserver(this); | 439 DCHECK(texture.identifier == 1 || texture.identifier == 2); |
| 558 for (int i = 0; i < 2; ++i) { | 440 |
| 559 Texture& texture = textures_[i]; | 441 scoped_ptr<TextureDefinition> definition(mailbox_manager_->ConsumeTexture( |
| 560 texture.info = NULL; | 442 GL_TEXTURE_2D, mailbox_names_[texture.identifier])); |
| 561 if (!texture.sent_to_client) | 443 if (definition.get()) { |
| 562 continue; | 444 texture.service_id = definition->ReleaseServiceId(); |
| 563 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | 445 texture.size = gfx::Size(definition->level_infos()[0][0].width, |
| 564 params.identifier = texture.client_id; | 446 definition->level_infos()[0][0].height); |
| 565 helper_->SendAcceleratedSurfaceRelease(params); | |
| 566 } | 447 } |
| 567 parent_stub_ = NULL; | 448 } |
| 449 | |
| 450 void TextureImageTransportSurface::ProduceTexture(Texture& texture) { | |
| 451 DCHECK(texture.service_id); | |
| 452 DCHECK(texture.identifier == 1 || texture.identifier == 2); | |
| 453 TextureManager* texture_manager = | |
| 454 helper_->stub()->decoder()->GetContextGroup()->texture_manager(); | |
| 455 DCHECK(texture.size.width() > 0 && texture.size.height() > 0); | |
| 456 TextureDefinition::LevelInfo info( | |
| 457 GL_TEXTURE_2D, GL_RGBA, texture.size.width(), texture.size.height(), 1, | |
| 458 0, GL_RGBA, GL_UNSIGNED_BYTE, true); | |
| 459 | |
| 460 TextureDefinition::LevelInfos level_infos; | |
| 461 level_infos.resize(1); | |
| 462 level_infos[0].resize(texture_manager->MaxLevelsForTarget(GL_TEXTURE_2D)); | |
| 463 level_infos[0][0] = info; | |
| 464 scoped_ptr<TextureDefinition> definition(new TextureDefinition( | |
| 465 GL_TEXTURE_2D, | |
| 466 texture.service_id, | |
| 467 true, | |
| 468 level_infos)); | |
| 469 mailbox_manager_->ProduceTexture( | |
| 470 GL_TEXTURE_2D, | |
| 471 mailbox_names_[texture.identifier], | |
| 472 definition.release(), | |
| 473 helper_->stub()->decoder()->GetContextGroup()->texture_manager()); | |
| 474 texture.service_id = 0; | |
| 568 } | 475 } |
| 569 | 476 |
| 570 } // namespace content | 477 } // namespace content |
| OLD | NEW |