Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: gpu/gles2_conform_support/egl/display.cc

Issue 1714883002: command_buffer_gles2: Implement EGL default Display as a global object (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@command_buffer_gles2-multiple-contexts
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "gpu/gles2_conform_support/egl/display.h" 5 #include "gpu/gles2_conform_support/egl/display.h"
6 6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <vector>
11 #include "base/at_exit.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/lazy_instance.h"
15 #include "gpu/command_buffer/client/gles2_implementation.h"
16 #include "gpu/command_buffer/client/gles2_lib.h"
17 #include "gpu/command_buffer/client/transfer_buffer.h"
18 #include "gpu/command_buffer/common/value_state.h"
19 #include "gpu/command_buffer/service/context_group.h"
20 #include "gpu/command_buffer/service/mailbox_manager.h"
21 #include "gpu/command_buffer/service/memory_tracking.h"
22 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
23 #include "gpu/command_buffer/service/valuebuffer_manager.h"
24 #include "gpu/gles2_conform_support/egl/config.h" 7 #include "gpu/gles2_conform_support/egl/config.h"
8 #include "gpu/gles2_conform_support/egl/context.h"
25 #include "gpu/gles2_conform_support/egl/surface.h" 9 #include "gpu/gles2_conform_support/egl/surface.h"
26 #include "gpu/gles2_conform_support/egl/test_support.h" 10 #include "gpu/gles2_conform_support/egl/thread_state.h"
27
28 namespace {
29 const int32_t kCommandBufferSize = 1024 * 1024;
30 const int32_t kTransferBufferSize = 512 * 1024;
31 }
32 11
33 namespace egl { 12 namespace egl {
34 13
35 // egl::Display is used for comformance tests and command_buffer_gles. We only 14 Display::Display() : is_initialized_(false) {
36 // need the exit manager for the command_buffer_gles library. 15 configs_[0] = nullptr;
37 // TODO(hendrikw): Find a cleaner solution for this. 16 configs_[1] = nullptr;
38 namespace {
39 base::LazyInstance<base::Lock>::Leaky g_init_lock;
40 int g_init_count;
41
42 #if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
43 base::AtExitManager* g_exit_manager;
44 #endif
45
46 void InitGlobal() {
47 base::AutoLock lock(g_init_lock.Get());
48 if (g_init_count == 0) {
49 gles2::Initialize();
50 }
51
52 #if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
53 #if defined(COMPONENT_BUILD)
54 if (g_command_buffer_gles_has_atexit_manager) {
55 ++g_init_count;
56 return;
57 }
58 #endif
59 if (g_init_count == 0) {
60 g_exit_manager = new base::AtExitManager;
61 }
62 #endif
63
64 ++g_init_count;
65
66 }
67 void ReleaseGlobal() {
68 base::AutoLock lock(g_init_lock.Get());
69 --g_init_count;
70 if (g_init_count == 0) {
71 gles2::Terminate();
72 }
73
74 #if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
75 #if defined(COMPONENT_BUILD)
76 if (g_command_buffer_gles_has_atexit_manager) {
77 return;
78 }
79 #endif
80 if (g_init_count == 0) {
81 delete g_exit_manager;
82 g_exit_manager = nullptr;
83 }
84 #endif
85 }
86 } // namespace
87
88
89 Display::Display(EGLNativeDisplayType display_id)
90 : display_id_(display_id),
91 is_initialized_(false),
92 create_offscreen_(false),
93 create_offscreen_width_(0),
94 create_offscreen_height_(0),
95 next_fence_sync_release_(1) {
96
97 InitGlobal();
98
99 } 17 }
100 18
101 Display::~Display() { 19 Display::~Display() {
102 20 surfaces_.clear();
103 ReleaseGlobal(); 21 contexts_.clear();
104 22 delete configs_[0];
23 delete configs_[1];
105 } 24 }
106 25
107 bool Display::Initialize() { 26 EGLBoolean Display::Initialize(ThreadState* ts, EGLint* major, EGLint* minor) {
27 base::Lock(lock_);
108 is_initialized_ = true; 28 is_initialized_ = true;
109 return true; 29
30 if (major)
31 *major = 1;
32 if (minor)
33 *minor = 4;
34 return ts->ReturnSuccess(EGL_TRUE);
110 } 35 }
111 36
112 bool Display::IsValidConfig(EGLConfig config) { 37 EGLBoolean Display::Terminate(ThreadState* ts) {
113 return (config != NULL) && (config == config_.get()); 38 base::Lock(lock_);
Sami Väisänen 2016/02/19 14:10:15 shouldn't this use base::AutoLock named variable?
Kimmo Kinnunen 2016/02/22 06:43:08 Done. (strange that even compiles)
39 is_initialized_ = false;
40 surfaces_.clear();
41 contexts_.clear();
42 return ts->ReturnSuccess(EGL_TRUE);
114 } 43 }
115 44
116 bool Display::ChooseConfigs(EGLConfig* configs, 45 const char* Display::QueryString(ThreadState* ts, EGLint name) {
117 EGLint config_size, 46 base::Lock(lock_);
118 EGLint* num_config) { 47 if (!is_initialized_)
119 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently 48 return ts->ReturnError<const char*>(EGL_NOT_INITIALIZED, nullptr);
120 // does not support finding or choosing configs. 49 switch (name) {
121 *num_config = 1; 50 case EGL_CLIENT_APIS:
122 if (configs != NULL) { 51 return ts->ReturnSuccess("OpenGL_ES");
123 if (config_ == NULL) { 52 case EGL_EXTENSIONS:
124 config_.reset(new Config); 53 return ts->ReturnSuccess("");
125 } 54 case EGL_VENDOR:
126 configs[0] = config_.get(); 55 return ts->ReturnSuccess("Google Inc.");
56 case EGL_VERSION:
57 return ts->ReturnSuccess("1.4");
58 default:
59 return ts->ReturnError<const char*>(EGL_BAD_PARAMETER, nullptr);
127 } 60 }
128 return true;
129 } 61 }
130 62
131 bool Display::GetConfigs(EGLConfig* configs, 63 EGLBoolean Display::ChooseConfig(ThreadState* ts,
132 EGLint config_size, 64 const EGLint* attrib_list,
133 EGLint* num_config) { 65 EGLConfig* configs,
134 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently 66 EGLint config_size,
135 // does not support finding or choosing configs. 67 EGLint* num_config) {
136 *num_config = 1; 68 base::Lock(lock_);
137 if (configs != NULL) { 69 if (!is_initialized_)
138 if (config_ == NULL) { 70 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
139 config_.reset(new Config); 71 if (num_config == nullptr)
72 return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE);
73 if (!Config::ValidateAttributeList(attrib_list))
74 return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
75 InitializeConfigsIfNeeded();
76 if (!configs)
77 config_size = 0;
78 *num_config = 0;
79 for (size_t i = 0; i < arraysize(configs_); ++i) {
80 if (configs_[i]->matches(attrib_list)) {
81 if (*num_config < config_size) {
82 configs[*num_config] = configs_[i];
83 }
84 ++*num_config;
140 } 85 }
141 configs[0] = config_.get();
142 } 86 }
143 return true; 87 return ts->ReturnSuccess(EGL_TRUE);
144 } 88 }
145 89
146 bool Display::GetConfigAttrib(EGLConfig config, 90 EGLBoolean Display::GetConfigs(ThreadState* ts,
147 EGLint attribute, 91 EGLConfig* configs,
148 EGLint* value) { 92 EGLint config_size,
149 const egl::Config* cfg = static_cast<egl::Config*>(config); 93 EGLint* num_config) {
150 return cfg->GetAttrib(attribute, value); 94 base::Lock(lock_);
95 if (!is_initialized_)
96 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
97 if (num_config == nullptr)
98 return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE);
99 InitializeConfigsIfNeeded();
100 if (!configs)
101 config_size = 0;
102 *num_config = arraysize(configs_);
103 size_t count =
104 std::min(arraysize(configs_), static_cast<size_t>(config_size));
105 std::copy(configs_, configs_ + count, configs);
106 return ts->ReturnSuccess(EGL_TRUE);
151 } 107 }
152 108
153 bool Display::IsValidNativeWindow(EGLNativeWindowType win) { 109 bool Display::IsValidNativeWindow(EGLNativeWindowType win) {
154 #if defined OS_WIN 110 #if defined OS_WIN
155 return ::IsWindow(win) != FALSE; 111 return ::IsWindow(win) != FALSE;
156 #else 112 #else
157 // TODO(alokp): Validate window handle. 113 // TODO(alokp): Validate window handle.
158 return true; 114 return true;
159 #endif // OS_WIN 115 #endif // OS_WIN
160 } 116 }
161 117
162 bool Display::IsValidSurface(EGLSurface surface) { 118 EGLBoolean Display::GetConfigAttrib(ThreadState* ts,
163 return (surface != NULL) && (surface == surface_.get()); 119 EGLConfig cfg,
164 } 120 EGLint attribute,
165 121 EGLint* value) {
166 EGLSurface Display::CreateWindowSurface(EGLConfig config, 122 base::Lock(lock_);
123 if (!is_initialized_)
124 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
125 const egl::Config* config = GetConfig(cfg);
126 if (!config)
127 return ts->ReturnError(EGL_BAD_CONFIG, EGL_FALSE);
128 if (!config->GetAttrib(attribute, value))
129 return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
130 return ts->ReturnSuccess(EGL_TRUE);
131 }
132
133 EGLSurface Display::CreatePbufferSurface(ThreadState* ts,
134 EGLConfig cfg,
135 const EGLint* attrib_list) {
136 base::Lock(lock_);
137 if (!is_initialized_)
138 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE);
139 const egl::Config* config = GetConfig(cfg);
140 if (!config)
141 return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
142 EGLint value = EGL_NONE;
143 config->GetAttrib(EGL_SURFACE_TYPE, &value);
144 if ((value & EGL_PBUFFER_BIT) == 0)
145 return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_SURFACE);
146 if (!egl::Surface::ValidatePbufferAttributeList(attrib_list))
147 return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
148
149 int width = 1;
150 int height = 1;
151 if (attrib_list) {
152 for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
153 switch (attr[0]) {
154 case EGL_WIDTH:
155 width = attr[1];
156 break;
157 case EGL_HEIGHT:
158 height = attr[1];
159 break;
160 }
161 }
162 }
163 scoped_refptr<gfx::GLSurface> gl_surface;
164 gl_surface =
165 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(width, height));
166 if (!gl_surface)
167 return ts->ReturnError(EGL_BAD_ALLOC, nullptr);
168 Surface* surface = new Surface(gl_surface.get());
169
170 surfaces_.emplace_back(surface);
171 return ts->ReturnSuccess<EGLSurface>(surface);
172 }
173
174 EGLSurface Display::CreateWindowSurface(ThreadState* ts,
175 EGLConfig cfg,
167 EGLNativeWindowType win, 176 EGLNativeWindowType win,
168 const EGLint* attrib_list) { 177 const EGLint* attrib_list) {
169 if (surface_ != NULL) { 178 base::Lock(lock_);
170 // We do not support more than one window surface. 179 if (!is_initialized_)
171 return EGL_NO_SURFACE; 180 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE);
172 } 181 const egl::Config* config = GetConfig(cfg);
173 182 if (!config)
174 { 183 return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
175 gpu::TransferBufferManager* manager = 184 EGLint value = EGL_NONE;
176 new gpu::TransferBufferManager(nullptr); 185 config->GetAttrib(EGL_SURFACE_TYPE, &value);
177 transfer_buffer_manager_ = manager; 186 if ((value & EGL_WINDOW_BIT) == 0)
178 manager->Initialize(); 187 return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
179 } 188 if (!IsValidNativeWindow(win))
180 scoped_ptr<gpu::CommandBufferService> command_buffer( 189 return ts->ReturnError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
181 new gpu::CommandBufferService(transfer_buffer_manager_.get())); 190 if (!Surface::ValidateWindowAttributeList(attrib_list))
182 if (!command_buffer->Initialize()) 191 return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
183 return NULL; 192 scoped_refptr<gfx::GLSurface> gl_surface;
184 193 gl_surface = gfx::GLSurface::CreateViewGLSurface(win);
185 scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( 194 if (!gl_surface)
186 NULL, NULL, new gpu::gles2::ShaderTranslatorCache, 195 return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
187 new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true)); 196 Surface* surface = new Surface(gl_surface.get());
188 197 surfaces_.emplace_back(surface);
189 decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); 198 return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
190 if (!decoder_.get()) 199 }
191 return EGL_NO_SURFACE; 200
192 201 EGLBoolean Display::DestroySurface(ThreadState* ts, EGLSurface sfe) {
193 gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(), 202 base::Lock(lock_);
194 decoder_.get(), 203 if (!is_initialized_)
195 NULL)); 204 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
196 205 Surface* surface = GetSurface(sfe);
197 decoder_->set_engine(gpu_scheduler_.get()); 206 if (!surface)
198 gfx::Size size(create_offscreen_width_, create_offscreen_height_); 207 return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
199 if (create_offscreen_) { 208 auto it = std::find(surfaces_.begin(), surfaces_.end(), surface);
200 gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); 209 DCHECK(it != surfaces_.end());
201 create_offscreen_ = false; 210 surfaces_.erase(it);
202 create_offscreen_width_ = 0; 211 return ts->ReturnSuccess(EGL_TRUE);
203 create_offscreen_height_ = 0; 212 }
213
214 EGLBoolean Display::ReleaseCurrent(ThreadState* ts) {
215 base::Lock(lock_);
216 if (!is_initialized_)
217 return ts->ReturnSuccess(EGL_TRUE);
218 ThreadState::AutoApplyCurrentContext aacc(ts);
219 Context* current_context = ts->current_context();
220 if (current_context) {
221 Surface* current_surface = ts->current_surface();
222 current_context->MakeCurrentRelease(current_surface);
223 ts->SetCurrent(nullptr, nullptr);
224 }
225 return ts->ReturnSuccess(EGL_TRUE);
226 }
227
228 EGLBoolean Display::MakeCurrent(ThreadState* ts,
229 EGLSurface draw,
230 EGLSurface read,
231 EGLSurface ctx) {
232 base::Lock(lock_);
233 if (!is_initialized_)
234 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
235 ThreadState::AutoApplyCurrentContext aacc(ts);
236 // Client might have called use because it changed some other gl binding
237 // global state. For example, the client might have called eglMakeCurrent on
238 // the same EGL as what command buffer uses. The client probably knows that
239 // this invalidates the internal state of command buffer, too. So reset the
240 // current context with aacc in any case, regardless whether context or
241 // surface pointer changes.
242 Surface* new_surface = GetSurface(draw);
243 if (!new_surface)
244 return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
245 new_surface = GetSurface(read);
246 if (!new_surface)
247 return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
248 egl::Context* new_context = GetContext(ctx);
249 if (!new_context)
250 return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE);
251 if (draw != read)
252 return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE);
253
254 Surface* current_surface = ts->current_surface();
255 Context* current_context = ts->current_context();
256
257 if (current_context != new_context &&
258 new_context->is_current_in_some_thread())
259 return EGL_BAD_ACCESS;
260
261 if (current_surface != new_surface &&
262 new_surface->is_current_in_some_thread())
263 return EGL_BAD_ACCESS;
264
265 bool success = true;
266 if (current_context == new_context) {
267 success =
268 new_context->MakeCurrentSwitchSurface(current_surface, new_surface);
204 } else { 269 } else {
205 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win); 270 if (current_context)
206 } 271 current_context->MakeCurrentRelease(current_surface);
207 if (!gl_surface_.get()) 272 success = new_context->MakeCurrent(new_surface);
208 return EGL_NO_SURFACE; 273 }
209 274 if (!success)
210 gl_context_ = gfx::GLContext::CreateGLContext(NULL, 275 return EGL_BAD_MATCH;
211 gl_surface_.get(), 276
212 gfx::PreferDiscreteGpu); 277 ts->SetCurrent(new_surface, new_context);
213 if (!gl_context_.get()) 278 return ts->ReturnSuccess(EGL_TRUE);
214 return EGL_NO_SURFACE; 279 }
215 280
216 gl_context_->MakeCurrent(gl_surface_.get()); 281 EGLBoolean Display::SwapBuffers(ThreadState* ts, EGLSurface sfe) {
217 282 base::Lock(lock_);
218 EGLint depth_size = 0; 283 if (!is_initialized_)
219 EGLint alpha_size = 0; 284 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
220 EGLint stencil_size = 0; 285 egl::Surface* surface = GetSurface(sfe);
221 GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size); 286 if (!surface)
222 GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size); 287 return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
223 GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size); 288 if (ts->current_surface() != surface)
224 std::vector<int32_t> attribs; 289 return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
225 attribs.push_back(EGL_DEPTH_SIZE); 290 ts->current_context()->FlushAndSwapBuffers(surface);
226 attribs.push_back(depth_size); 291 return ts->ReturnSuccess(EGL_TRUE);
227 attribs.push_back(EGL_ALPHA_SIZE); 292 }
228 attribs.push_back(alpha_size); 293
229 attribs.push_back(EGL_STENCIL_SIZE); 294 EGLContext Display::CreateContext(ThreadState* ts,
230 attribs.push_back(stencil_size); 295 EGLConfig cfg,
231 // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null
232 attribs.push_back(EGL_NONE);
233
234 if (!decoder_->Initialize(gl_surface_.get(),
235 gl_context_.get(),
236 gl_surface_->IsOffscreen(),
237 size,
238 gpu::gles2::DisallowedFeatures(),
239 attribs)) {
240 return EGL_NO_SURFACE;
241 }
242
243 command_buffer->SetPutOffsetChangeCallback(
244 base::Bind(&gpu::GpuScheduler::PutChanged,
245 base::Unretained(gpu_scheduler_.get())));
246 command_buffer->SetGetBufferChangeCallback(
247 base::Bind(&gpu::GpuScheduler::SetGetBuffer,
248 base::Unretained(gpu_scheduler_.get())));
249
250 scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper(
251 new gpu::gles2::GLES2CmdHelper(command_buffer.get()));
252 if (!cmd_helper->Initialize(kCommandBufferSize))
253 return NULL;
254
255 scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer(
256 cmd_helper.get()));
257
258 command_buffer_.reset(command_buffer.release());
259 transfer_buffer_.reset(transfer_buffer.release());
260 gles2_cmd_helper_.reset(cmd_helper.release());
261 surface_.reset(new Surface(win));
262
263 return surface_.get();
264 }
265
266 void Display::DestroySurface(EGLSurface surface) {
267 DCHECK(IsValidSurface(surface));
268 gpu_scheduler_.reset();
269 if (decoder_.get()) {
270 decoder_->Destroy(true);
271 }
272 decoder_.reset();
273 gl_surface_ = NULL;
274 gl_context_ = NULL;
275 surface_.reset();
276 }
277
278 void Display::SwapBuffers(EGLSurface surface) {
279 DCHECK(IsValidSurface(surface));
280 context_->SwapBuffers();
281 }
282
283 bool Display::IsValidContext(EGLContext ctx) {
284 return (ctx != NULL) && (ctx == context_.get());
285 }
286
287 EGLContext Display::CreateContext(EGLConfig config,
288 EGLContext share_ctx, 296 EGLContext share_ctx,
289 const EGLint* attrib_list) { 297 const EGLint* attrib_list) {
290 DCHECK(IsValidConfig(config)); 298 base::Lock(lock_);
291 // TODO(alokp): Add support for shared contexts. 299 if (!is_initialized_)
292 if (share_ctx != NULL) 300 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_CONTEXT);
293 return EGL_NO_CONTEXT; 301 if (share_ctx != EGL_NO_CONTEXT) {
294 302 egl::Context* share_context = GetContext(share_ctx);
295 DCHECK(command_buffer_ != NULL); 303 if (!share_context)
296 DCHECK(transfer_buffer_.get()); 304 return ts->ReturnError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
297 305 // TODO(alokp): Add support for shared contexts.
298 bool bind_generates_resources = true; 306 return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_CONTEXT);
299 bool lose_context_when_out_of_memory = false; 307 }
300 bool support_client_side_arrays = true; 308 if (!egl::Context::ValidateAttributeList(attrib_list))
301 309 return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
302 context_.reset( 310 const egl::Config* config = GetConfig(cfg);
303 new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(), 311 if (!config)
304 NULL, 312 return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
305 transfer_buffer_.get(), 313 scoped_refptr<Context> context(new Context(this, config));
306 bind_generates_resources, 314 if (!context)
307 lose_context_when_out_of_memory, 315 return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
308 support_client_side_arrays, 316 contexts_.emplace_back(context.get());
309 this)); 317 return ts->ReturnSuccess<EGLContext>(context.get());
310 318 }
311 if (!context_->Initialize( 319
312 kTransferBufferSize, 320 EGLBoolean Display::DestroyContext(ThreadState* ts, EGLContext ctx) {
313 kTransferBufferSize / 2, 321 ThreadState::AutoApplyCurrentContext aacc(ts);
314 kTransferBufferSize * 2, 322 {
315 gpu::gles2::GLES2Implementation::kNoLimit)) { 323 base::Lock(lock_);
316 return EGL_NO_CONTEXT; 324 if (!is_initialized_)
317 } 325 return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
318 326 egl::Context* context = GetContext(ctx);
319 context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); 327 if (!context)
320 context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); 328 return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE);
321 329 scoped_refptr<Context> local_context(context);
322 return context_.get(); 330 auto it = std::find(contexts_.begin(), contexts_.end(), context);
323 } 331 DCHECK(it != contexts_.end());
324 332 contexts_.erase(it);
325 void Display::DestroyContext(EGLContext ctx) { 333 Surface* current_surface = ts->current_context() == local_context
326 DCHECK(IsValidContext(ctx)); 334 ? ts->current_surface()
327 context_.reset(); 335 : nullptr;
328 transfer_buffer_.reset(); 336 local_context->SetDestroyed(current_surface);
329 } 337 }
330 338 return ts->ReturnSuccess(EGL_TRUE);
331 bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) {
332 if (ctx == EGL_NO_CONTEXT) {
333 gles2::SetGLContext(NULL);
334 } else {
335 DCHECK(IsValidSurface(draw));
336 DCHECK(IsValidSurface(read));
337 DCHECK(IsValidContext(ctx));
338 gles2::SetGLContext(context_.get());
339 gl_context_->MakeCurrent(gl_surface_.get());
340 }
341 return true;
342 }
343
344 gpu::Capabilities Display::GetCapabilities() {
345 return decoder_->GetCapabilities();
346 }
347
348 int32_t Display::CreateImage(ClientBuffer buffer,
349 size_t width,
350 size_t height,
351 unsigned internalformat) {
352 NOTIMPLEMENTED();
353 return -1;
354 }
355
356 void Display::DestroyImage(int32_t id) {
357 NOTIMPLEMENTED();
358 }
359
360 int32_t Display::CreateGpuMemoryBufferImage(size_t width,
361 size_t height,
362 unsigned internalformat,
363 unsigned usage) {
364 NOTIMPLEMENTED();
365 return -1;
366 }
367
368 void Display::SignalQuery(uint32_t query, const base::Closure& callback) {
369 NOTIMPLEMENTED();
370 }
371
372 void Display::SetLock(base::Lock*) {
373 NOTIMPLEMENTED();
374 }
375
376 bool Display::IsGpuChannelLost() {
377 NOTIMPLEMENTED();
378 return false;
379 }
380
381 void Display::EnsureWorkVisible() {
382 // This is only relevant for out-of-process command buffers.
383 }
384
385 gpu::CommandBufferNamespace Display::GetNamespaceID() const {
386 return gpu::CommandBufferNamespace::IN_PROCESS;
387 }
388
389 uint64_t Display::GetCommandBufferID() const {
390 return 0;
391 }
392
393 int32_t Display::GetExtraCommandBufferData() const {
394 return 0;
395 } 339 }
396 340
397 uint64_t Display::GenerateFenceSyncRelease() { 341 uint64_t Display::GenerateFenceSyncRelease() {
342 base::Lock(lock_);
398 return next_fence_sync_release_++; 343 return next_fence_sync_release_++;
399 } 344 }
400 345
401 bool Display::IsFenceSyncRelease(uint64_t release) { 346 bool Display::IsFenceSyncRelease(uint64_t release) {
347 base::Lock(lock_);
402 return release > 0 && release < next_fence_sync_release_; 348 return release > 0 && release < next_fence_sync_release_;
403 } 349 }
404 350
405 bool Display::IsFenceSyncFlushed(uint64_t release) { 351 bool Display::IsFenceSyncFlushed(uint64_t release) {
406 return IsFenceSyncRelease(release); 352 return IsFenceSyncRelease(release);
407 } 353 }
408 354
409 bool Display::IsFenceSyncFlushReceived(uint64_t release) { 355 bool Display::IsFenceSyncFlushReceived(uint64_t release) {
410 return IsFenceSyncRelease(release); 356 return IsFenceSyncRelease(release);
411 } 357 }
412 358
413 void Display::SignalSyncToken(const gpu::SyncToken& sync_token, 359 void Display::InitializeConfigsIfNeeded() {
414 const base::Closure& callback) { 360 if (!configs_[0]) {
415 NOTIMPLEMENTED(); 361 // The interface offers separate configs for window and pbuffer.
362 // This way we can record the client intention at context creation time.
363 // The GL implementation (gfx::GLContext and gfx::GLSurface) needs this
364 // distinction when creating a context.
365 configs_[0] = new Config(EGL_WINDOW_BIT);
366 configs_[1] = new Config(EGL_PBUFFER_BIT);
367 }
416 } 368 }
417 369
418 bool Display::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) { 370 const Config* Display::GetConfig(EGLConfig config) {
419 return false; 371 if (config == configs_[0])
372 return configs_[0];
373 if (config == configs_[1])
374 return configs_[1];
375 return nullptr;
376 }
377
378 Surface* Display::GetSurface(EGLSurface surface) {
379 auto it = std::find(surfaces_.begin(), surfaces_.end(), surface);
380 if (it == surfaces_.end())
381 return nullptr;
382 return it->get();
383 }
384
385 Context* Display::GetContext(EGLContext context) {
386 auto it = std::find(contexts_.begin(), contexts_.end(), context);
387 if (it == contexts_.end())
388 return nullptr;
389 return it->get();
420 } 390 }
421 391
422 } // namespace egl 392 } // namespace egl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698