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