blob: c856b2aae85f53cdc8b1afa721217e6d65562285 [file] [log] [blame]
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001//
daniel@transgaming.comc6f7f9d2012-01-27 15:40:00 +00002// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.come979ead2010-09-23 18:03:14 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Display.cpp: Implements the egl::Display class, representing the abstract
8// display on which graphics are drawn. Implements EGLDisplay.
9// [EGL 1.4] section 2.1.2 page 3.
10
11#include "libEGL/Display.h"
12
13#include <algorithm>
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000014#include <map>
daniel@transgaming.come979ead2010-09-23 18:03:14 +000015#include <vector>
16
17#include "common/debug.h"
jbauman@chromium.org06d7a752011-04-30 01:02:52 +000018#include "libGLESv2/mathutil.h"
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +000019#include "libGLESv2/utilities.h"
daniel@transgaming.come979ead2010-09-23 18:03:14 +000020
21#include "libEGL/main.h"
22
daniel@transgaming.come979ead2010-09-23 18:03:14 +000023
24namespace egl
25{
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000026namespace
27{
28 typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
29 DisplayMap displays;
30}
31
32egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)
33{
34 if (displays.find(displayId) != displays.end())
35 {
36 return displays[displayId];
37 }
38
39 egl::Display *display = NULL;
40
41 if (displayId == EGL_DEFAULT_DISPLAY)
42 {
43 display = new egl::Display(displayId, (HDC)NULL, false);
44 }
45 else if (displayId == EGL_SOFTWARE_DISPLAY_ANGLE)
46 {
47 display = new egl::Display(displayId, (HDC)NULL, true);
48 }
49 else
50 {
51 // FIXME: Check if displayId is a valid display device context
52
53 display = new egl::Display(displayId, (HDC)displayId, false);
54 }
55
56 displays[displayId] = display;
57 return display;
58}
59
60Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext)
daniel@transgaming.come979ead2010-09-23 18:03:14 +000061{
daniel@transgaming.come979ead2010-09-23 18:03:14 +000062
63 mMinSwapInterval = 1;
64 mMaxSwapInterval = 1;
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000065 mSoftwareDevice = software;
66 mDisplayId = displayId;
daniel@transgaming.com621ce052012-10-31 17:52:29 +000067 mRenderer = NULL;
daniel@transgaming.come979ead2010-09-23 18:03:14 +000068}
69
70Display::~Display()
71{
72 terminate();
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000073
74 DisplayMap::iterator thisDisplay = displays.find(mDisplayId);
75
76 if (thisDisplay != displays.end())
77 {
78 displays.erase(thisDisplay);
79 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +000080}
81
82bool Display::initialize()
83{
84 if (isInitialized())
85 {
86 return true;
87 }
88
daniel@transgaming.com621ce052012-10-31 17:52:29 +000089 HMODULE hModule = NULL;
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000090 if (mSoftwareDevice)
91 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +000092 hModule = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000093 }
94 else
95 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +000096 hModule = GetModuleHandle(TEXT("d3d9.dll"));
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000097 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +000098 if (hModule == NULL)
daniel@transgaming.come979ead2010-09-23 18:03:14 +000099 {
100 terminate();
101 return false;
102 }
103
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000104 mRenderer = glCreateRenderer(this, hModule, mDc);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000105 EGLint status = EGL_BAD_ALLOC;
106 if (mRenderer)
107 status = mRenderer->initialize();
108 if (status != EGL_SUCCESS)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000109 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000110 terminate();
111 return error(status, false);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000112 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000113 D3DCAPS9 deviceCaps = mRenderer->getDeviceCaps(); // D3D9_REPLACE
114 IDirect3D9 *d3d9 = mRenderer->getD3D(); // D3D9_REPLACE
115 UINT adapter = mRenderer->getAdapter(); // D3D9_REPLACE
116 D3DDEVTYPE deviceType = mRenderer->getDeviceType(); // D3D9_REPLACE
117 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
118
119 mMinSwapInterval = 4;
120 mMaxSwapInterval = 0;
121
122 // START D3D9_REPLACE
123 if (deviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);}
124 if (deviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);}
125 if (deviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);}
126 if (deviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);}
127 if (deviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);}
128
129 const D3DFORMAT renderTargetFormats[] =
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000130 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000131 D3DFMT_A1R5G5B5,
132 // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
133 D3DFMT_A8R8G8B8,
134 D3DFMT_R5G6B5,
135 // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format
136 D3DFMT_X8R8G8B8
137 };
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000138
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000139 const D3DFORMAT depthStencilFormats[] =
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000140 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000141 D3DFMT_UNKNOWN,
142 // D3DFMT_D16_LOCKABLE,
143 D3DFMT_D32,
144 // D3DFMT_D15S1,
145 D3DFMT_D24S8,
146 D3DFMT_D24X8,
147 // D3DFMT_D24X4S4,
148 D3DFMT_D16,
149 // D3DFMT_D32F_LOCKABLE,
150 // D3DFMT_D24FS8
151 };
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000152
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000153 D3DDISPLAYMODE currentDisplayMode;
154 d3d9->GetAdapterDisplayMode(adapter, &currentDisplayMode);
155
156 ConfigSet configSet;
157
158 for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++)
159 {
160 D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex];
161
162 HRESULT result = d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
163
164 if (SUCCEEDED(result))
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000165 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000166 for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000167 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000168 D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
169 HRESULT result = D3D_OK;
daniel@transgaming.coma114c272011-04-22 04:18:50 +0000170
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000171 if(depthStencilFormat != D3DFMT_UNKNOWN)
172 {
173 result = d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
174 }
175
176 if (SUCCEEDED(result))
177 {
daniel@transgaming.coma114c272011-04-22 04:18:50 +0000178 if(depthStencilFormat != D3DFMT_UNKNOWN)
179 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000180 result = d3d9->CheckDepthStencilMatch(adapter, deviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
daniel@transgaming.coma114c272011-04-22 04:18:50 +0000181 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000182
183 if (SUCCEEDED(result))
184 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000185 // FIXME: enumerate multi-sampling
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000186
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000187 configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
188 deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000189 }
190 }
191 }
192 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000193 }
194 // END D3D9_REPLACE
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000195
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000196 // Give the sorted configs a unique ID and store them internally
197 EGLint index = 1;
198 for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
199 {
200 Config configuration = *config;
201 configuration.mConfigID = index;
202 index++;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000203
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000204 mConfigSet.mSet.insert(configuration);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000205 }
206
207 if (!isInitialized())
208 {
209 terminate();
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000210 return false;
211 }
212
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000213 initExtensionString();
214
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000215 mVertexShaderCache.initialize(device);
216 mPixelShaderCache.initialize(device);
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000217
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000218 return true;
219}
220
221void Display::terminate()
222{
223 while (!mSurfaceSet.empty())
224 {
225 destroySurface(*mSurfaceSet.begin());
226 }
227
228 while (!mContextSet.empty())
229 {
230 destroyContext(*mContextSet.begin());
231 }
232
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000233 mVertexShaderCache.clear();
234 mPixelShaderCache.clear();
235
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000236 glDestroyRenderer(mRenderer);
237 mRenderer = NULL;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000238}
239
240bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
241{
242 return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
243}
244
245bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
246{
247 const egl::Config *configuration = mConfigSet.get(config);
248
249 switch (attribute)
250 {
251 case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break;
252 case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break;
253 case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break;
254 case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break;
255 case EGL_RED_SIZE: *value = configuration->mRedSize; break;
256 case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break;
257 case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break;
258 case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break;
259 case EGL_CONFIG_ID: *value = configuration->mConfigID; break;
260 case EGL_LEVEL: *value = configuration->mLevel; break;
261 case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break;
262 case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break;
263 case EGL_SAMPLES: *value = configuration->mSamples; break;
264 case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break;
265 case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break;
266 case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break;
267 case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break;
268 case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break;
269 case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break;
270 case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break;
271 case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break;
272 case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break;
273 case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break;
274 case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break;
275 case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break;
276 case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break;
277 case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break;
278 case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
279 case EGL_CONFORMANT: *value = configuration->mConformant; break;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000280 case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break;
281 case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break;
282 case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000283 default:
284 return false;
285 }
286
287 return true;
288}
289
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000290
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000291
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000292EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000293{
294 const Config *configuration = mConfigSet.get(config);
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000295 EGLint postSubBufferSupported = EGL_FALSE;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000296
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000297 if (attribList)
298 {
299 while (*attribList != EGL_NONE)
300 {
301 switch (attribList[0])
302 {
303 case EGL_RENDER_BUFFER:
304 switch (attribList[1])
305 {
306 case EGL_BACK_BUFFER:
307 break;
308 case EGL_SINGLE_BUFFER:
309 return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported
310 default:
311 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
312 }
313 break;
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000314 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
315 postSubBufferSupported = attribList[1];
316 break;
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000317 case EGL_VG_COLORSPACE:
318 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
319 case EGL_VG_ALPHA_FORMAT:
320 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
321 default:
322 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
323 }
324
325 attribList += 2;
326 }
327 }
328
329 if (hasExistingWindowSurface(window))
330 {
331 return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
332 }
333
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000334 if (mRenderer->testDeviceLost())
daniel@transgaming.comcf23c452011-11-09 17:47:26 +0000335 {
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000336 if (!restoreLostDevice())
337 return EGL_NO_SURFACE;
338 }
339
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000340 Surface *surface = new Surface(this, configuration, window, postSubBufferSupported);
jbauman@chromium.org4e297702011-05-12 23:04:07 +0000341
342 if (!surface->initialize())
343 {
344 delete surface;
345 return EGL_NO_SURFACE;
346 }
347
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000348 mSurfaceSet.insert(surface);
349
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000350 return success(surface);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000351}
352
jbauman@chromium.org4e297702011-05-12 23:04:07 +0000353EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000354{
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000355 EGLint width = 0, height = 0;
356 EGLenum textureFormat = EGL_NO_TEXTURE;
357 EGLenum textureTarget = EGL_NO_TEXTURE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000358 const Config *configuration = mConfigSet.get(config);
359
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000360 if (attribList)
361 {
362 while (*attribList != EGL_NONE)
363 {
364 switch (attribList[0])
365 {
366 case EGL_WIDTH:
367 width = attribList[1];
368 break;
369 case EGL_HEIGHT:
370 height = attribList[1];
371 break;
372 case EGL_LARGEST_PBUFFER:
373 if (attribList[1] != EGL_FALSE)
374 UNIMPLEMENTED(); // FIXME
375 break;
376 case EGL_TEXTURE_FORMAT:
377 switch (attribList[1])
378 {
379 case EGL_NO_TEXTURE:
380 case EGL_TEXTURE_RGB:
381 case EGL_TEXTURE_RGBA:
382 textureFormat = attribList[1];
383 break;
384 default:
385 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
386 }
387 break;
388 case EGL_TEXTURE_TARGET:
389 switch (attribList[1])
390 {
391 case EGL_NO_TEXTURE:
392 case EGL_TEXTURE_2D:
393 textureTarget = attribList[1];
394 break;
395 default:
396 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
397 }
398 break;
399 case EGL_MIPMAP_TEXTURE:
400 if (attribList[1] != EGL_FALSE)
401 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
402 break;
403 case EGL_VG_COLORSPACE:
404 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
405 case EGL_VG_ALPHA_FORMAT:
406 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
407 default:
408 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
409 }
410
411 attribList += 2;
412 }
413 }
414
415 if (width < 0 || height < 0)
416 {
417 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
418 }
419
420 if (width == 0 || height == 0)
421 {
422 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
423 }
424
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000425 if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height)))
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000426 {
427 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
428 }
429
430 if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
431 (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
432 {
433 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
434 }
435
436 if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
437 {
438 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
439 }
440
441 if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
442 (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
443 {
444 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
445 }
446
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000447 if (mRenderer->testDeviceLost())
daniel@transgaming.comcf23c452011-11-09 17:47:26 +0000448 {
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000449 if (!restoreLostDevice())
450 return EGL_NO_SURFACE;
451 }
452
jbauman@chromium.org4e297702011-05-12 23:04:07 +0000453 Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
454
455 if (!surface->initialize())
456 {
457 delete surface;
458 return EGL_NO_SURFACE;
459 }
460
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000461 mSurfaceSet.insert(surface);
462
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000463 return success(surface);
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000464}
465
daniel@transgaming.com4ff960d2011-11-09 17:47:09 +0000466EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000467{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000468 if (!mRenderer)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000469 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000470 return NULL;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000471 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000472 else if (mRenderer->testDeviceLost()) // Lost device
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000473 {
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000474 if (!restoreLostDevice())
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000475 return NULL;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000476 }
477
478 const egl::Config *config = mConfigSet.get(configHandle);
479
daniel@transgaming.com4ff960d2011-11-09 17:47:09 +0000480 gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000481 mContextSet.insert(context);
482
483 return context;
484}
485
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000486bool Display::restoreLostDevice()
487{
daniel@transgaming.comcf23c452011-11-09 17:47:26 +0000488 for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
489 {
490 if ((*ctx)->isResetNotificationEnabled())
491 return false; // If reset notifications have been requested, application must delete all contexts first
492 }
493
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000494 // Release surface resources to make the Reset() succeed
495 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
496 {
497 (*surface)->release();
498 }
499
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000500 mVertexShaderCache.clear();
501 mPixelShaderCache.clear();
502
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000503 if (!mRenderer->resetDevice())
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000504 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000505 return error(EGL_BAD_ALLOC, false);
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000506 }
507
508 // Restore any surfaces that may have been lost
509 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
510 {
511 (*surface)->resetSwapChain();
512 }
513
514 return true;
515}
516
517
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000518void Display::destroySurface(egl::Surface *surface)
519{
daniel@transgaming.comc556fa52011-05-26 14:13:29 +0000520 delete surface;
521 mSurfaceSet.erase(surface);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000522}
523
524void Display::destroyContext(gl::Context *context)
525{
526 glDestroyContext(context);
527 mContextSet.erase(context);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000528}
529
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000530void Display::notifyDeviceLost()
531{
532 for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
533 {
534 (*context)->markContextLost();
535 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000536 mRenderer->markDeviceLost();
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000537 error(EGL_CONTEXT_LOST);
538}
539
daniel@transgaming.com3b1703f2011-05-11 15:36:26 +0000540bool Display::isInitialized() const
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000541{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000542 return mRenderer != NULL && mConfigSet.size() > 0;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000543}
544
545bool Display::isValidConfig(EGLConfig config)
546{
547 return mConfigSet.get(config) != NULL;
548}
549
550bool Display::isValidContext(gl::Context *context)
551{
552 return mContextSet.find(context) != mContextSet.end();
553}
554
555bool Display::isValidSurface(egl::Surface *surface)
556{
daniel@transgaming.comc556fa52011-05-26 14:13:29 +0000557 return mSurfaceSet.find(surface) != mSurfaceSet.end();
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000558}
559
560bool Display::hasExistingWindowSurface(HWND window)
561{
562 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
563 {
564 if ((*surface)->getWindowHandle() == window)
565 {
566 return true;
567 }
568 }
569
570 return false;
571}
572
573EGLint Display::getMinSwapInterval()
574{
575 return mMinSwapInterval;
576}
577
578EGLint Display::getMaxSwapInterval()
579{
580 return mMaxSwapInterval;
581}
582
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000583void Display::initExtensionString()
584{
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +0000585 HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000586 bool shareHandleSupported = mRenderer->getShareHandleSupport();
daniel@transgaming.com1a1fe242011-09-26 18:25:45 +0000587
588 mExtensionString = "";
589
daniel@transgaming.com8747f182011-11-09 17:50:38 +0000590 // Multi-vendor (EXT) extensions
591 mExtensionString += "EGL_EXT_create_context_robustness ";
592
593 // ANGLE-specific extensions
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000594 if (shareHandleSupported)
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000595 {
daniel@transgaming.com1a1fe242011-09-26 18:25:45 +0000596 mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
597 }
598
599 mExtensionString += "EGL_ANGLE_query_surface_pointer ";
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +0000600
601 if (swiftShader)
602 {
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000603 mExtensionString += "EGL_ANGLE_software_display ";
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +0000604 }
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000605
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000606 if (shareHandleSupported)
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000607 {
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000608 mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle ";
609 }
610
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000611 mExtensionString += "EGL_NV_post_sub_buffer";
612
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000613 std::string::size_type end = mExtensionString.find_last_not_of(' ');
614 if (end != std::string::npos)
615 {
616 mExtensionString.resize(end+1);
617 }
618}
619
620const char *Display::getExtensionString() const
621{
622 return mExtensionString.c_str();
623}
624
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000625IDirect3DVertexShader9 *Display::createVertexShader(const DWORD *function, size_t length)
626{
627 return mVertexShaderCache.create(function, length);
628}
629
630IDirect3DPixelShader9 *Display::createPixelShader(const DWORD *function, size_t length)
631{
632 return mPixelShaderCache.create(function, length);
633}
634
daniel@transgaming.comc6f7f9d2012-01-27 15:40:00 +0000635
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000636}