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 3 // found in the LICENSE file. 4 5 #include "gpu/gles2_conform_support/egl/display.h" 6 7 #include <vector> 8 #include "base/bind.h" 9 #include "base/bind_helpers.h" 10 #include "gpu/command_buffer/client/gles2_implementation.h" 11 #include "gpu/command_buffer/client/gles2_lib.h" 12 #include "gpu/command_buffer/client/transfer_buffer.h" 13 #include "gpu/command_buffer/service/context_group.h" 14 #include "gpu/command_buffer/service/mailbox_manager.h" 15 #include "gpu/command_buffer/service/memory_tracking.h" 16 #include "gpu/command_buffer/service/transfer_buffer_manager.h" 17 #include "gpu/gles2_conform_support/egl/config.h" 18 #include "gpu/gles2_conform_support/egl/surface.h" 19 20 namespace { 21 const int32 kCommandBufferSize = 1024 * 1024; 22 const int32 kTransferBufferSize = 512 * 1024; 23 } 24 25 namespace egl { 26 27 Display::Display(EGLNativeDisplayType display_id) 28 : display_id_(display_id), 29 is_initialized_(false), 30 create_offscreen_(false), 31 create_offscreen_width_(0), 32 create_offscreen_height_(0) { 33 } 34 35 Display::~Display() { 36 gles2::Terminate(); 37 } 38 39 bool Display::Initialize() { 40 gles2::Initialize(); 41 is_initialized_ = true; 42 return true; 43 } 44 45 bool Display::IsValidConfig(EGLConfig config) { 46 return (config != NULL) && (config == config_.get()); 47 } 48 49 bool Display::ChooseConfigs(EGLConfig* configs, 50 EGLint config_size, 51 EGLint* num_config) { 52 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently 53 // does not support finding or choosing configs. 54 *num_config = 1; 55 if (configs != NULL) { 56 if (config_ == NULL) { 57 config_.reset(new Config); 58 } 59 configs[0] = config_.get(); 60 } 61 return true; 62 } 63 64 bool Display::GetConfigs(EGLConfig* configs, 65 EGLint config_size, 66 EGLint* num_config) { 67 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently 68 // does not support finding or choosing configs. 69 *num_config = 1; 70 if (configs != NULL) { 71 if (config_ == NULL) { 72 config_.reset(new Config); 73 } 74 configs[0] = config_.get(); 75 } 76 return true; 77 } 78 79 bool Display::GetConfigAttrib(EGLConfig config, 80 EGLint attribute, 81 EGLint* value) { 82 const egl::Config* cfg = static_cast<egl::Config*>(config); 83 return cfg->GetAttrib(attribute, value); 84 } 85 86 bool Display::IsValidNativeWindow(EGLNativeWindowType win) { 87 #if defined OS_WIN 88 return ::IsWindow(win) != FALSE; 89 #else 90 // TODO(alokp): Validate window handle. 91 return true; 92 #endif // OS_WIN 93 } 94 95 bool Display::IsValidSurface(EGLSurface surface) { 96 return (surface != NULL) && (surface == surface_.get()); 97 } 98 99 EGLSurface Display::CreateWindowSurface(EGLConfig config, 100 EGLNativeWindowType win, 101 const EGLint* attrib_list) { 102 if (surface_ != NULL) { 103 // We do not support more than one window surface. 104 return EGL_NO_SURFACE; 105 } 106 107 { 108 gpu::TransferBufferManager* manager = new gpu::TransferBufferManager(); 109 transfer_buffer_manager_.reset(manager); 110 manager->Initialize(); 111 } 112 scoped_ptr<gpu::CommandBufferService> command_buffer( 113 new gpu::CommandBufferService(transfer_buffer_manager_.get())); 114 if (!command_buffer->Initialize()) 115 return NULL; 116 117 scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( 118 NULL, NULL, new gpu::gles2::ShaderTranslatorCache, NULL, true)); 119 120 decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); 121 if (!decoder_.get()) 122 return EGL_NO_SURFACE; 123 124 gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(), 125 decoder_.get(), 126 NULL)); 127 128 decoder_->set_engine(gpu_scheduler_.get()); 129 gfx::Size size(create_offscreen_width_, create_offscreen_height_); 130 if (create_offscreen_) { 131 gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); 132 create_offscreen_ = false; 133 create_offscreen_width_ = 0; 134 create_offscreen_height_ = 0; 135 } else { 136 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win); 137 } 138 if (!gl_surface_.get()) 139 return EGL_NO_SURFACE; 140 141 gl_context_ = gfx::GLContext::CreateGLContext(NULL, 142 gl_surface_.get(), 143 gfx::PreferDiscreteGpu); 144 if (!gl_context_.get()) 145 return EGL_NO_SURFACE; 146 147 gl_context_->MakeCurrent(gl_surface_.get()); 148 149 EGLint depth_size = 0; 150 EGLint alpha_size = 0; 151 EGLint stencil_size = 0; 152 GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size); 153 GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size); 154 GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size); 155 std::vector<int32> attribs; 156 attribs.push_back(EGL_DEPTH_SIZE); 157 attribs.push_back(depth_size); 158 attribs.push_back(EGL_ALPHA_SIZE); 159 attribs.push_back(alpha_size); 160 attribs.push_back(EGL_STENCIL_SIZE); 161 attribs.push_back(stencil_size); 162 // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null 163 attribs.push_back(EGL_NONE); 164 165 if (!decoder_->Initialize(gl_surface_.get(), 166 gl_context_.get(), 167 gl_surface_->IsOffscreen(), 168 size, 169 gpu::gles2::DisallowedFeatures(), 170 attribs)) { 171 return EGL_NO_SURFACE; 172 } 173 174 command_buffer->SetPutOffsetChangeCallback( 175 base::Bind(&gpu::GpuScheduler::PutChanged, 176 base::Unretained(gpu_scheduler_.get()))); 177 command_buffer->SetGetBufferChangeCallback( 178 base::Bind(&gpu::GpuScheduler::SetGetBuffer, 179 base::Unretained(gpu_scheduler_.get()))); 180 181 scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper( 182 new gpu::gles2::GLES2CmdHelper(command_buffer.get())); 183 if (!cmd_helper->Initialize(kCommandBufferSize)) 184 return NULL; 185 186 scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer( 187 cmd_helper.get())); 188 189 command_buffer_.reset(command_buffer.release()); 190 transfer_buffer_.reset(transfer_buffer.release()); 191 gles2_cmd_helper_.reset(cmd_helper.release()); 192 surface_.reset(new Surface(win)); 193 194 return surface_.get(); 195 } 196 197 void Display::DestroySurface(EGLSurface surface) { 198 DCHECK(IsValidSurface(surface)); 199 gpu_scheduler_.reset(); 200 if (decoder_.get()) { 201 decoder_->Destroy(true); 202 } 203 decoder_.reset(); 204 gl_surface_ = NULL; 205 gl_context_ = NULL; 206 surface_.reset(); 207 } 208 209 void Display::SwapBuffers(EGLSurface surface) { 210 DCHECK(IsValidSurface(surface)); 211 context_->SwapBuffers(); 212 } 213 214 bool Display::IsValidContext(EGLContext ctx) { 215 return (ctx != NULL) && (ctx == context_.get()); 216 } 217 218 EGLContext Display::CreateContext(EGLConfig config, 219 EGLContext share_ctx, 220 const EGLint* attrib_list) { 221 DCHECK(IsValidConfig(config)); 222 // TODO(alokp): Add support for shared contexts. 223 if (share_ctx != NULL) 224 return EGL_NO_CONTEXT; 225 226 DCHECK(command_buffer_ != NULL); 227 DCHECK(transfer_buffer_.get()); 228 229 bool bind_generates_resources = true; 230 bool lose_context_when_out_of_memory = false; 231 232 context_.reset( 233 new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(), 234 NULL, 235 transfer_buffer_.get(), 236 bind_generates_resources, 237 lose_context_when_out_of_memory, 238 this)); 239 240 if (!context_->Initialize( 241 kTransferBufferSize, 242 kTransferBufferSize / 2, 243 kTransferBufferSize * 2, 244 gpu::gles2::GLES2Implementation::kNoLimit)) { 245 return EGL_NO_CONTEXT; 246 } 247 248 context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); 249 context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); 250 251 return context_.get(); 252 } 253 254 void Display::DestroyContext(EGLContext ctx) { 255 DCHECK(IsValidContext(ctx)); 256 context_.reset(); 257 transfer_buffer_.reset(); 258 } 259 260 bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) { 261 if (ctx == EGL_NO_CONTEXT) { 262 gles2::SetGLContext(NULL); 263 } else { 264 DCHECK(IsValidSurface(draw)); 265 DCHECK(IsValidSurface(read)); 266 DCHECK(IsValidContext(ctx)); 267 gles2::SetGLContext(context_.get()); 268 } 269 return true; 270 } 271 272 gpu::Capabilities Display::GetCapabilities() { 273 return decoder_->GetCapabilities(); 274 } 275 276 gfx::GpuMemoryBuffer* Display::CreateGpuMemoryBuffer( 277 size_t width, 278 size_t height, 279 unsigned internalformat, 280 unsigned usage, 281 int32* id) { 282 NOTIMPLEMENTED(); 283 return NULL; 284 } 285 286 void Display::DestroyGpuMemoryBuffer(int32 id) { 287 NOTIMPLEMENTED(); 288 } 289 290 uint32 Display::InsertSyncPoint() { 291 NOTIMPLEMENTED(); 292 return 0u; 293 } 294 295 uint32 Display::InsertFutureSyncPoint() { 296 NOTIMPLEMENTED(); 297 return 0u; 298 } 299 300 void Display::RetireSyncPoint(uint32 sync_point) { 301 NOTIMPLEMENTED(); 302 } 303 304 void Display::SignalSyncPoint(uint32 sync_point, 305 const base::Closure& callback) { 306 NOTIMPLEMENTED(); 307 } 308 309 void Display::SignalQuery(uint32 query, const base::Closure& callback) { 310 NOTIMPLEMENTED(); 311 } 312 313 void Display::SetSurfaceVisible(bool visible) { 314 NOTIMPLEMENTED(); 315 } 316 317 void Display::Echo(const base::Closure& callback) { 318 NOTIMPLEMENTED(); 319 } 320 321 uint32 Display::CreateStreamTexture(uint32 texture_id) { 322 NOTIMPLEMENTED(); 323 return 0; 324 } 325 326 } // namespace egl 327