display.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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_lib.h" 11#include "gpu/command_buffer/client/transfer_buffer.h" 12#include "gpu/command_buffer/service/context_group.h" 13#include "gpu/command_buffer/service/transfer_buffer_manager.h" 14#include "gpu/gles2_conform_support/egl/config.h" 15#include "gpu/gles2_conform_support/egl/surface.h" 16 17namespace { 18const int32 kCommandBufferSize = 1024 * 1024; 19const int32 kTransferBufferSize = 512 * 1024; 20} 21 22namespace egl { 23 24Display::Display(EGLNativeDisplayType display_id) 25 : display_id_(display_id), 26 is_initialized_(false), 27 create_offscreen_(false), 28 create_offscreen_width_(0), 29 create_offscreen_height_(0) { 30} 31 32Display::~Display() { 33 gles2::Terminate(); 34} 35 36bool Display::Initialize() { 37 gles2::Initialize(); 38 is_initialized_ = true; 39 return true; 40} 41 42bool Display::IsValidConfig(EGLConfig config) { 43 return (config != NULL) && (config == config_.get()); 44} 45 46bool Display::ChooseConfigs(EGLConfig* configs, 47 EGLint config_size, 48 EGLint* num_config) { 49 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently 50 // does not support finding or choosing configs. 51 *num_config = 1; 52 if (configs != NULL) { 53 if (config_ == NULL) { 54 config_.reset(new Config); 55 } 56 configs[0] = config_.get(); 57 } 58 return true; 59} 60 61bool Display::GetConfigs(EGLConfig* configs, 62 EGLint config_size, 63 EGLint* num_config) { 64 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently 65 // does not support finding or choosing configs. 66 *num_config = 1; 67 if (configs != NULL) { 68 if (config_ == NULL) { 69 config_.reset(new Config); 70 } 71 configs[0] = config_.get(); 72 } 73 return true; 74} 75 76bool Display::GetConfigAttrib(EGLConfig config, 77 EGLint attribute, 78 EGLint* value) { 79 const egl::Config* cfg = static_cast<egl::Config*>(config); 80 return cfg->GetAttrib(attribute, value); 81} 82 83bool Display::IsValidNativeWindow(EGLNativeWindowType win) { 84#if defined OS_WIN 85 return ::IsWindow(win) != FALSE; 86#else 87 // TODO(alokp): Validate window handle. 88 return true; 89#endif // OS_WIN 90} 91 92bool Display::IsValidSurface(EGLSurface surface) { 93 return (surface != NULL) && (surface == surface_.get()); 94} 95 96EGLSurface Display::CreateWindowSurface(EGLConfig config, 97 EGLNativeWindowType win, 98 const EGLint* attrib_list) { 99 if (surface_ != NULL) { 100 // We do not support more than one window surface. 101 return EGL_NO_SURFACE; 102 } 103 104 { 105 gpu::TransferBufferManager* manager = new gpu::TransferBufferManager(); 106 transfer_buffer_manager_.reset(manager); 107 manager->Initialize(); 108 } 109 scoped_ptr<gpu::CommandBufferService> command_buffer( 110 new gpu::CommandBufferService(transfer_buffer_manager_.get())); 111 if (!command_buffer->Initialize()) 112 return NULL; 113 114 gpu::gles2::ContextGroup::Ref group(new gpu::gles2::ContextGroup(NULL, 115 NULL, 116 NULL, 117 true)); 118 119 decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); 120 if (!decoder_.get()) 121 return EGL_NO_SURFACE; 122 123 gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(), 124 decoder_.get(), 125 NULL)); 126 127 decoder_->set_engine(gpu_scheduler_.get()); 128 gfx::Size size(create_offscreen_width_, create_offscreen_height_); 129 if (create_offscreen_) { 130 gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, size); 131 create_offscreen_ = false; 132 create_offscreen_width_ = 0; 133 create_offscreen_height_ = 0; 134 } else { 135 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(false, win); 136 } 137 if (!gl_surface_.get()) 138 return EGL_NO_SURFACE; 139 140 gl_context_ = gfx::GLContext::CreateGLContext(NULL, 141 gl_surface_.get(), 142 gfx::PreferDiscreteGpu); 143 if (!gl_context_.get()) 144 return EGL_NO_SURFACE; 145 146 gl_context_->MakeCurrent(gl_surface_); 147 148 EGLint depth_size = 0; 149 EGLint alpha_size = 0; 150 EGLint stencil_size = 0; 151 GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size); 152 GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size); 153 GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size); 154 std::vector<int32> attribs; 155 attribs.push_back(EGL_DEPTH_SIZE); 156 attribs.push_back(depth_size); 157 attribs.push_back(EGL_ALPHA_SIZE); 158 attribs.push_back(alpha_size); 159 attribs.push_back(EGL_STENCIL_SIZE); 160 attribs.push_back(stencil_size); 161 // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null 162 attribs.push_back(EGL_NONE); 163 164 if (!decoder_->Initialize(gl_surface_.get(), 165 gl_context_.get(), 166 gl_surface_->IsOffscreen(), 167 size, 168 gpu::gles2::DisallowedFeatures(), 169 NULL, 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 197void 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 209void Display::SwapBuffers(EGLSurface surface) { 210 DCHECK(IsValidSurface(surface)); 211 context_->SwapBuffers(); 212} 213 214bool Display::IsValidContext(EGLContext ctx) { 215 return (ctx != NULL) && (ctx == context_.get()); 216} 217 218EGLContext 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 bool share_resources = share_ctx != NULL; 229 context_.reset(new gpu::gles2::GLES2Implementation( 230 gles2_cmd_helper_.get(), 231 NULL, 232 transfer_buffer_.get(), 233 share_resources, 234 true)); 235 236 if (!context_->Initialize( 237 kTransferBufferSize, 238 kTransferBufferSize / 2, 239 kTransferBufferSize * 2)) { 240 return EGL_NO_CONTEXT; 241 } 242 243 context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); 244 context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); 245 246 return context_.get(); 247} 248 249void Display::DestroyContext(EGLContext ctx) { 250 DCHECK(IsValidContext(ctx)); 251 context_.reset(); 252 transfer_buffer_.reset(); 253} 254 255bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) { 256 if (ctx == EGL_NO_CONTEXT) { 257 gles2::SetGLContext(NULL); 258 } else { 259 DCHECK(IsValidSurface(draw)); 260 DCHECK(IsValidSurface(read)); 261 DCHECK(IsValidContext(ctx)); 262 gles2::SetGLContext(context_.get()); 263 } 264 return true; 265} 266 267} // namespace egl 268