blob: e4b259064f7dab336d4aa5bd5d18e01224088399 [file] [log] [blame]
daniel@transgaming.com95a758f2012-07-12 15:17:06 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
8// such as the client area of a window, including any back buffers.
9// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
10
11#include <tchar.h>
12
13#include "libEGL/Surface.h"
14
15#include "common/debug.h"
16#include "libGLESv2/Texture.h"
17
18#include "libEGL/main.h"
19#include "libEGL/Display.h"
20
21#include <dwmapi.h>
22
23namespace egl
24{
25
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000026Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported)
27 : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
28{
29 mSwapChain = NULL;
30 mBackBuffer = NULL;
31 mDepthStencil = NULL;
32 mRenderTarget = NULL;
33 mOffscreenTexture = NULL;
34 mShareHandle = NULL;
35 mTexture = NULL;
36 mTextureFormat = EGL_NO_TEXTURE;
37 mTextureTarget = EGL_NO_TEXTURE;
38
39 mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
40 mRenderBuffer = EGL_BACK_BUFFER;
41 mSwapBehavior = EGL_BUFFER_PRESERVED;
42 mSwapInterval = -1;
43 setSwapInterval(1);
44
45 subclassWindow();
46}
47
48Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
49 : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
50{
51 mSwapChain = NULL;
52 mBackBuffer = NULL;
53 mDepthStencil = NULL;
54 mRenderTarget = NULL;
55 mOffscreenTexture = NULL;
56 mWindowSubclassed = false;
57 mTexture = NULL;
58 mTextureFormat = textureFormat;
59 mTextureTarget = textureType;
60
61 mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
62 mRenderBuffer = EGL_BACK_BUFFER;
63 mSwapBehavior = EGL_BUFFER_PRESERVED;
64 mSwapInterval = -1;
65 setSwapInterval(1);
66}
67
68Surface::~Surface()
69{
70 unsubclassWindow();
71 release();
72}
73
74bool Surface::initialize()
75{
76 ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil);
77
78 if (!resetSwapChain())
79 return false;
80
81 // Modify present parameters for this window, if we are composited,
82 // to minimize the amount of queuing done by DWM between our calls to
83 // present and the actual screen.
84 if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) {
85 BOOL isComposited;
86 HRESULT result = DwmIsCompositionEnabled(&isComposited);
87 if (SUCCEEDED(result) && isComposited) {
88 DWM_PRESENT_PARAMETERS presentParams;
89 memset(&presentParams, 0, sizeof(presentParams));
90 presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
91 presentParams.cBuffer = 2;
92
93 result = DwmSetPresentParameters(mWindow, &presentParams);
94 if (FAILED(result))
95 ERR("Unable to set present parameters: 0x%08X", result);
96 }
97 }
98
99 return true;
100}
101
102void Surface::release()
103{
104 if (mSwapChain)
105 {
106 mSwapChain->Release();
107 mSwapChain = NULL;
108 }
109
110 if (mBackBuffer)
111 {
112 mBackBuffer->Release();
113 mBackBuffer = NULL;
114 }
115
116 if (mDepthStencil)
117 {
118 mDepthStencil->Release();
119 mDepthStencil = NULL;
120 }
121
122 if (mRenderTarget)
123 {
124 mRenderTarget->Release();
125 mRenderTarget = NULL;
126 }
127
128 if (mOffscreenTexture)
129 {
130 mOffscreenTexture->Release();
131 mOffscreenTexture = NULL;
132 }
133
134 if (mTexture)
135 {
136 mTexture->releaseTexImage();
137 mTexture = NULL;
138 }
139
140 mShareHandle = NULL;
141}
142
143bool Surface::resetSwapChain()
144{
145 if (!mWindow)
146 {
147 return resetSwapChain(mWidth, mHeight);
148 }
149
150 RECT windowRect;
151 if (!GetClientRect(getWindowHandle(), &windowRect))
152 {
153 ASSERT(false);
154
155 ERR("Could not retrieve the window dimensions");
156 return false;
157 }
158
159 return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
160}
161
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000162// D3D9_REPLACE
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000163bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
164{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000165 renderer::Renderer *renderer = mDisplay->getRenderer();
166 IDirect3DDevice9 *device = renderer->getDevice();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000167
168 if (device == NULL)
169 {
170 return false;
171 }
172
173 // Evict all non-render target textures to system memory and release all resources
174 // before reallocating them to free up as much video memory as possible.
175 device->EvictManagedResources();
176
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000177 HRESULT result;
178
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000179 // Release specific resources to free up memory for the new render target, while the
180 // old render target still exists for the purpose of preserving its contents.
181 if (mSwapChain)
182 {
183 mSwapChain->Release();
184 mSwapChain = NULL;
185 }
186
187 if (mBackBuffer)
188 {
189 mBackBuffer->Release();
190 mBackBuffer = NULL;
191 }
192
193 if (mOffscreenTexture)
194 {
195 mOffscreenTexture->Release();
196 mOffscreenTexture = NULL;
197 }
198
199 if (mDepthStencil)
200 {
201 mDepthStencil->Release();
202 mDepthStencil = NULL;
203 }
204
205 mShareHandle = NULL;
206 HANDLE *pShareHandle = NULL;
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000207 if (!mWindow && renderer->getShareHandleSupport())
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000208 {
209 pShareHandle = &mShareHandle;
210 }
211
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000212 result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
213 mConfig->mRenderTargetFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000214 if (FAILED(result))
215 {
216 ERR("Could not create offscreen texture: %08lX", result);
217 release();
218
219 if(isDeviceLostError(result))
220 {
221 mDisplay->notifyDeviceLost();
222 return false;
223 }
224 else
225 {
226 return error(EGL_BAD_ALLOC, false);
227 }
228 }
229
230 IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
231
232 result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
233 ASSERT(SUCCEEDED(result));
234
235 if (oldRenderTarget)
236 {
237 RECT rect =
238 {
239 0, 0,
240 mWidth, mHeight
241 };
242
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000243 if (rect.right > static_cast<LONG>(backbufferWidth))
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000244 {
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000245 rect.right = backbufferWidth;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000246 }
247
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000248 if (rect.bottom > static_cast<LONG>(backbufferHeight))
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000249 {
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000250 rect.bottom = backbufferHeight;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000251 }
252
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000253 renderer->endScene();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000254
255 result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
256 ASSERT(SUCCEEDED(result));
257
258 oldRenderTarget->Release();
259 }
260
261 if (mWindow)
262 {
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000263 D3DPRESENT_PARAMETERS presentParameters = {0};
264 presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
265 presentParameters.BackBufferCount = 1;
266 presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
267 presentParameters.EnableAutoDepthStencil = FALSE;
268 presentParameters.Flags = 0;
269 presentParameters.hDeviceWindow = getWindowHandle();
270 presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
271 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
272 presentParameters.PresentationInterval = mPresentInterval;
273 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
274 presentParameters.Windowed = TRUE;
275 presentParameters.BackBufferWidth = backbufferWidth;
276 presentParameters.BackBufferHeight = backbufferHeight;
277
278 // http://crbug.com/140239
apatrick@chromium.org85e44192012-08-17 20:58:01 +0000279 // http://crbug.com/143434
280 //
281 // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
282 // when using the integrated Intel. This rounds the width up rather than down.
283 //
284 // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
285 // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000286 D3DADAPTER_IDENTIFIER9* adapterIdentifier = renderer->getAdapterIdentifier();
apatrick@chromium.org85e44192012-08-17 20:58:01 +0000287 if (adapterIdentifier->VendorId == VENDOR_ID_INTEL)
288 {
289 presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
290 }
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000291
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000292 result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
293
294 if (FAILED(result))
295 {
296 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
297
298 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
299 release();
300
301 if(isDeviceLostError(result))
302 {
303 mDisplay->notifyDeviceLost();
304 return false;
305 }
306 else
307 {
308 return error(EGL_BAD_ALLOC, false);
309 }
310 }
311
312 result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
313 ASSERT(SUCCEEDED(result));
314 }
315
316 if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
317 {
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000318 result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, mConfig->mDepthStencilFormat, D3DMULTISAMPLE_NONE,
319 0, FALSE, &mDepthStencil, NULL);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000320
321 if (FAILED(result))
322 {
323 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
324
325 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
326 release();
327
328 if(isDeviceLostError(result))
329 {
330 mDisplay->notifyDeviceLost();
331 return false;
332 }
333 else
334 {
335 return error(EGL_BAD_ALLOC, false);
336 }
337 }
338 }
339
apatrick@chromium.org0c71fd42012-08-10 18:08:47 +0000340 mWidth = backbufferWidth;
341 mHeight = backbufferHeight;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000342
343 mPresentIntervalDirty = false;
344 return true;
345}
346
347bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
348{
349 if (!mSwapChain)
350 {
351 return true;
352 }
353
354 if (x + width > mWidth)
355 {
356 width = mWidth - x;
357 }
358
359 if (y + height > mHeight)
360 {
361 height = mHeight - y;
362 }
363
364 if (width == 0 || height == 0)
365 {
366 return true;
367 }
368
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000369 renderer::Renderer *renderer = mDisplay->getRenderer();
370 IDirect3DDevice9 *device = renderer->getDevice();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000371
372 // Disable all pipeline operations
373 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
374 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
375 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
376 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
377 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
378 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
379 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
380 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
381 device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
382 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
383 device->SetPixelShader(NULL);
384 device->SetVertexShader(NULL);
385
386 device->SetRenderTarget(0, mBackBuffer);
387 device->SetDepthStencilSurface(NULL);
388
389 device->SetTexture(0, mOffscreenTexture);
390 device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
391 device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
392 device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
393 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
394 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
395 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
396 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
397 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
398
399 D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f};
400 device->SetViewport(&viewport);
401
402 float x1 = x - 0.5f;
403 float y1 = (mHeight - y - height) - 0.5f;
404 float x2 = (x + width) - 0.5f;
405 float y2 = (mHeight - y) - 0.5f;
406
407 float u1 = x / float(mWidth);
408 float v1 = y / float(mHeight);
409 float u2 = (x + width) / float(mWidth);
410 float v2 = (y + height) / float(mHeight);
411
412 float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
413 {x2, y1, 0.0f, 1.0f, u2, v2},
414 {x2, y2, 0.0f, 1.0f, u2, v1},
415 {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v
416
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000417 renderer->startScene();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000418 device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000419 renderer->endScene();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000420
421 device->SetTexture(0, NULL);
422
423 RECT rect =
424 {
425 x, mHeight - y - height,
426 x + width, mHeight - y
427 };
428
429 HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
430
431 gl::Context *context = static_cast<gl::Context*>(glGetCurrentContext());
432 if (context)
433 {
434 context->markAllStateDirty();
435 }
436
437 if (isDeviceLostError(result))
438 {
439 mDisplay->notifyDeviceLost();
440 return false;
441 }
442
443 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
444 {
445 return error(EGL_BAD_ALLOC, false);
446 }
447
448 ASSERT(SUCCEEDED(result));
449
450 checkForOutOfDateSwapChain();
451
452 return true;
453}
454
455HWND Surface::getWindowHandle()
456{
457 return mWindow;
458}
459
460
461#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
462#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
463
464static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
465{
466 if (message == WM_SIZE)
467 {
468 Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));
469 if(surf)
470 {
471 surf->checkForOutOfDateSwapChain();
472 }
473 }
474 WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
475 return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
476}
477
478void Surface::subclassWindow()
479{
480 if (!mWindow)
481 {
482 return;
483 }
484
485 DWORD processId;
486 DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
487 if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
488 {
489 return;
490 }
491
492 SetLastError(0);
493 LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
494 if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
495 {
496 mWindowSubclassed = false;
497 return;
498 }
499
500 SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
501 SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
502 mWindowSubclassed = true;
503}
504
505void Surface::unsubclassWindow()
506{
507 if(!mWindowSubclassed)
508 {
509 return;
510 }
511
512 // un-subclass
513 LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));
514
515 // Check the windowproc is still SurfaceWindowProc.
516 // If this assert fails, then it is likely the application has subclassed the
517 // hwnd as well and did not unsubclass before destroying its EGL context. The
518 // application should be modified to either subclass before initializing the
519 // EGL context, or to unsubclass before destroying the EGL context.
520 if(parentWndFunc)
521 {
522 LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
523 ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
524 }
525
526 RemoveProp(mWindow, kSurfaceProperty);
527 RemoveProp(mWindow, kParentWndProc);
528 mWindowSubclassed = false;
529}
530
531bool Surface::checkForOutOfDateSwapChain()
532{
533 RECT client;
534 if (!GetClientRect(getWindowHandle(), &client))
535 {
536 ASSERT(false);
537 return false;
538 }
539
540 // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
541 int clientWidth = client.right - client.left;
542 int clientHeight = client.bottom - client.top;
543 bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
544
545 if (sizeDirty || mPresentIntervalDirty)
546 {
547 resetSwapChain(clientWidth, clientHeight);
548 if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
549 {
550 glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
551 }
552
553 return true;
554 }
555 return false;
556}
557
558DWORD Surface::convertInterval(EGLint interval)
559{
560 switch(interval)
561 {
562 case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
563 case 1: return D3DPRESENT_INTERVAL_ONE;
564 case 2: return D3DPRESENT_INTERVAL_TWO;
565 case 3: return D3DPRESENT_INTERVAL_THREE;
566 case 4: return D3DPRESENT_INTERVAL_FOUR;
567 default: UNREACHABLE();
568 }
569
570 return D3DPRESENT_INTERVAL_DEFAULT;
571}
572
573bool Surface::swap()
574{
575 return swapRect(0, 0, mWidth, mHeight);
576}
577
578bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
579{
580 if (!mPostSubBufferSupported)
581 {
582 // Spec is not clear about how this should be handled.
583 return true;
584 }
585
586 return swapRect(x, y, width, height);
587}
588
589EGLint Surface::getWidth() const
590{
591 return mWidth;
592}
593
594EGLint Surface::getHeight() const
595{
596 return mHeight;
597}
598
599EGLint Surface::isPostSubBufferSupported() const
600{
601 return mPostSubBufferSupported;
602}
603
604// Increments refcount on surface.
605// caller must Release() the returned surface
606IDirect3DSurface9 *Surface::getRenderTarget()
607{
608 if (mRenderTarget)
609 {
610 mRenderTarget->AddRef();
611 }
612
613 return mRenderTarget;
614}
615
616// Increments refcount on surface.
617// caller must Release() the returned surface
618IDirect3DSurface9 *Surface::getDepthStencil()
619{
620 if (mDepthStencil)
621 {
622 mDepthStencil->AddRef();
623 }
624
625 return mDepthStencil;
626}
627
628IDirect3DTexture9 *Surface::getOffscreenTexture()
629{
630 if (mOffscreenTexture)
631 {
632 mOffscreenTexture->AddRef();
633 }
634
635 return mOffscreenTexture;
636}
637
638void Surface::setSwapInterval(EGLint interval)
639{
640 if (mSwapInterval == interval)
641 {
642 return;
643 }
644
645 mSwapInterval = interval;
646 mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());
647 mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());
648
649 mPresentInterval = convertInterval(mSwapInterval);
650 mPresentIntervalDirty = true;
651}
652
653EGLenum Surface::getTextureFormat() const
654{
655 return mTextureFormat;
656}
657
658EGLenum Surface::getTextureTarget() const
659{
660 return mTextureTarget;
661}
662
663void Surface::setBoundTexture(gl::Texture2D *texture)
664{
665 mTexture = texture;
666}
667
668gl::Texture2D *Surface::getBoundTexture() const
669{
670 return mTexture;
671}
672
673D3DFORMAT Surface::getFormat() const
674{
675 return mConfig->mRenderTargetFormat;
676}
677}