Commit f4490e22 by apatrick@chromium.org

Implemented EGL_NV_post_sub_buffer.

The change to the sample is just to demonstrate how I tested it. I won't check in the stuff under samples/. It's not clear to me what eglPostSubBufferNV should do if EGL_POST_SUB_BUFFER_SUPPORTED_NV is false. At the moment it fails silently as though it was called on the wrong surface type: "If <surface> is a back-buffered surface, then the requested portion of the color buffer is copied to the native window associated with that surface. If <surface> is a single-buffered window, pixmap, or pbuffer surface, eglSwapBuffers and eglPostSubBufferNV have no effect." Review URL: http://codereview.appspot.com/5345050 git-svn-id: https://angleproject.googlecode.com/svn/trunk@902 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 343373ab
...@@ -159,6 +159,14 @@ ...@@ -159,6 +159,14 @@
'gles2_book/TextureWrap/TextureWrap.c', 'gles2_book/TextureWrap/TextureWrap.c',
], ],
}, },
{
'target_name': 'post_sub_buffer',
'type': 'executable',
'dependencies': ['es_util'],
'sources': [
'gles2_book/PostSubBuffer/PostSubBuffer.c',
],
},
], ],
}], }],
], ],
......
...@@ -22,10 +22,16 @@ ...@@ -22,10 +22,16 @@
#include <stdlib.h> #include <stdlib.h>
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h>
#include "esUtil.h" #include "esUtil.h"
#include "esUtil_win.h" #include "esUtil_win.h"
///
// Extensions
//
PFNEGLPOSTSUBBUFFERNVPROC eglPostSubBufferNV;
/// ///
...@@ -35,7 +41,7 @@ ...@@ -35,7 +41,7 @@
// //
EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay, EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
EGLContext* eglContext, EGLSurface* eglSurface, EGLContext* eglContext, EGLSurface* eglSurface,
EGLint attribList[]) EGLint* configAttribList, EGLint* surfaceAttribList)
{ {
EGLint numConfigs; EGLint numConfigs;
EGLint majorVersion; EGLint majorVersion;
...@@ -45,7 +51,7 @@ EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay, ...@@ -45,7 +51,7 @@ EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
EGLSurface surface; EGLSurface surface;
EGLConfig config; EGLConfig config;
EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
// Get Display // Get Display
display = eglGetDisplay(GetDC(hWnd)); display = eglGetDisplay(GetDC(hWnd));
if ( display == EGL_NO_DISPLAY ) if ( display == EGL_NO_DISPLAY )
...@@ -59,6 +65,9 @@ EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay, ...@@ -59,6 +65,9 @@ EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
return EGL_FALSE; return EGL_FALSE;
} }
// Bind to extensions
eglPostSubBufferNV = (PFNEGLPOSTSUBBUFFERNVPROC) eglGetProcAddress("eglPostSubBufferNV");
// Get configs // Get configs
if ( !eglGetConfigs(display, NULL, 0, &numConfigs) ) if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )
{ {
...@@ -66,13 +75,13 @@ EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay, ...@@ -66,13 +75,13 @@ EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
} }
// Choose config // Choose config
if ( !eglChooseConfig(display, attribList, &config, 1, &numConfigs) ) if ( !eglChooseConfig(display, configAttribList, &config, 1, &numConfigs) )
{ {
return EGL_FALSE; return EGL_FALSE;
} }
// Create a surface // Create a surface
surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL); surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, surfaceAttribList);
if ( surface == EGL_NO_SURFACE ) if ( surface == EGL_NO_SURFACE )
{ {
return EGL_FALSE; return EGL_FALSE;
...@@ -128,10 +137,11 @@ void ESUTIL_API esInitContext ( ESContext *esContext ) ...@@ -128,10 +137,11 @@ void ESUTIL_API esInitContext ( ESContext *esContext )
// ES_WINDOW_DEPTH - specifies that a depth buffer should be created // ES_WINDOW_DEPTH - specifies that a depth buffer should be created
// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created // ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created // ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
// ES_WINDOW_POST_SUB_BUFFER_SUPPORTED - specifies that EGL_POST_SUB_BUFFER_NV is supported.
// //
GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint width, GLint height, GLuint flags ) GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint width, GLint height, GLuint flags )
{ {
EGLint attribList[] = EGLint configAttribList[] =
{ {
EGL_RED_SIZE, 5, EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6, EGL_GREEN_SIZE, 6,
...@@ -142,6 +152,11 @@ GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint ...@@ -142,6 +152,11 @@ GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint
EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0, EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
EGL_NONE EGL_NONE
}; };
EGLint surfaceAttribList[] =
{
EGL_POST_SUB_BUFFER_SUPPORTED_NV, flags & (ES_WINDOW_POST_SUB_BUFFER_SUPPORTED) ? EGL_TRUE : EGL_FALSE,
EGL_NONE, EGL_NONE
};
if ( esContext == NULL ) if ( esContext == NULL )
{ {
...@@ -161,7 +176,8 @@ GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint ...@@ -161,7 +176,8 @@ GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint
&esContext->eglDisplay, &esContext->eglDisplay,
&esContext->eglContext, &esContext->eglContext,
&esContext->eglSurface, &esContext->eglSurface,
attribList) ) configAttribList,
surfaceAttribList ) )
{ {
return GL_FALSE; return GL_FALSE;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
// //
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h>
#ifdef __cplusplus #ifdef __cplusplus
...@@ -44,9 +45,10 @@ extern "C" { ...@@ -44,9 +45,10 @@ extern "C" {
#define ES_WINDOW_DEPTH 2 #define ES_WINDOW_DEPTH 2
/// esCreateWindow flag - stencil buffer /// esCreateWindow flag - stencil buffer
#define ES_WINDOW_STENCIL 4 #define ES_WINDOW_STENCIL 4
/// esCreateWindow flat - multi-sample buffer /// esCreateWindow flag - multi-sample buffer
#define ES_WINDOW_MULTISAMPLE 8 #define ES_WINDOW_MULTISAMPLE 8
/// esCreateWindow flag - EGL_POST_SUB_BUFFER_NV supported.
#define ES_WINDOW_POST_SUB_BUFFER_SUPPORTED 16
/// ///
// Types // Types
...@@ -88,6 +90,13 @@ typedef struct ...@@ -88,6 +90,13 @@ typedef struct
/// ///
// Extensions
//
extern PFNEGLPOSTSUBBUFFERNVPROC eglPostSubBufferNV;
///
// Public Functions // Public Functions
// //
...@@ -110,6 +119,7 @@ void ESUTIL_API esInitContext ( ESContext *esContext ); ...@@ -110,6 +119,7 @@ void ESUTIL_API esInitContext ( ESContext *esContext );
/// ES_WINDOW_DEPTH - specifies that a depth buffer should be created /// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
/// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created /// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
/// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created /// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
/// ES_WINDOW_POST_SUB_BUFFER_SUPPORTED - specifies that EGL_POST_SUB_BUFFER_NV is supported.
/// \return GL_TRUE if window creation is succesful, GL_FALSE otherwise /// \return GL_TRUE if window creation is succesful, GL_FALSE otherwise
GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint width, GLint height, GLuint flags ); GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint width, GLint height, GLuint flags );
......
// Based on a sample from:
//
// Book: OpenGL(R) ES 2.0 Programming Guide
// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10: 0321502795
// ISBN-13: 9780321502797
// Publisher: Addison-Wesley Professional
// URLs: http://safari.informit.com/9780321563835
// http://www.opengles-book.com
//
// PostSubBuffer.c
//
// This is a simple example that draws a rotating cube in perspective
// using a vertex shader to transform the object, posting only a subrectangle
// to the window surface.
//
#include <stdlib.h>
#include "esUtil.h"
#define WINDOW_WIDTH 320
#define WINDOW_HEIGHT 240
typedef struct
{
// Handle to a program object
GLuint programObject;
// Attribute locations
GLint positionLoc;
// Uniform locations
GLint mvpLoc;
// Vertex daata
GLfloat *vertices;
GLushort *indices;
int numIndices;
// Rotation angle
GLfloat angle;
// MVP matrix
ESMatrix mvpMatrix;
} UserData;
///
// Initialize the shader and program object
//
int Init ( ESContext *esContext )
{
UserData *userData = esContext->userData;
GLbyte vShaderStr[] =
"uniform mat4 u_mvpMatrix; \n"
"attribute vec4 a_position; \n"
"void main() \n"
"{ \n"
" gl_Position = u_mvpMatrix * a_position; \n"
"} \n";
GLbyte fShaderStr[] =
"precision mediump float; \n"
"void main() \n"
"{ \n"
" gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); \n"
"} \n";
// Load the shaders and get a linked program object
userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
// Get the attribute locations
userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
// Get the uniform locations
userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" );
// Generate the vertex data
userData->numIndices = esGenCube( 1.0, &userData->vertices,
NULL, NULL, &userData->indices );
// Starting rotation angle for the cube
userData->angle = 45.0f;
// Clear the whole window surface.
glClearColor ( 0.0f, 0.0f, 1.0f, 0.0f );
glClear ( GL_COLOR_BUFFER_BIT );
eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
return TRUE;
}
///
// Update MVP matrix based on time
//
void Update ( ESContext *esContext, float deltaTime )
{
UserData *userData = (UserData*) esContext->userData;
ESMatrix perspective;
ESMatrix modelview;
float aspect;
// Compute a rotation angle based on time to rotate the cube
userData->angle += ( deltaTime * 40.0f );
if( userData->angle >= 360.0f )
userData->angle -= 360.0f;
// Compute the window aspect ratio
aspect = (GLfloat) esContext->width / (GLfloat) esContext->height;
// Generate a perspective matrix with a 60 degree FOV
esMatrixLoadIdentity( &perspective );
esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f );
// Generate a model view matrix to rotate/translate the cube
esMatrixLoadIdentity( &modelview );
// Translate away from the viewer
esTranslate( &modelview, 0.0, 0.0, -2.0 );
// Rotate the cube
esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 );
// Compute the final MVP by multiplying the
// modevleiw and perspective matrices together
esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective );
}
///
// Draw a triangle using the shader pair created in Init()
//
void Draw ( ESContext *esContext )
{
UserData *userData = esContext->userData;
// Set the viewport
glViewport ( 0, 0, esContext->width, esContext->height );
// Clear the color buffer
glClear ( GL_COLOR_BUFFER_BIT );
// Use the program object
glUseProgram ( userData->programObject );
// Load the vertex position
glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
GL_FALSE, 3 * sizeof(GLfloat), userData->vertices );
glEnableVertexAttribArray ( userData->positionLoc );
// Load the MVP matrix
glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] );
// Draw the cube
glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_SHORT, userData->indices );
eglPostSubBufferNV ( esContext->eglDisplay, esContext->eglSurface, 60, 60, WINDOW_WIDTH - 120, WINDOW_HEIGHT - 120 );
}
///
// Cleanup
//
void ShutDown ( ESContext *esContext )
{
UserData *userData = esContext->userData;
if ( userData->vertices != NULL )
{
free ( userData->vertices );
}
if ( userData->indices != NULL )
{
free ( userData->indices );
}
// Delete program object
glDeleteProgram ( userData->programObject );
}
int main ( int argc, char *argv[] )
{
ESContext esContext;
UserData userData;
esInitContext ( &esContext );
esContext.userData = &userData;
esCreateWindow ( &esContext, TEXT("Simple Vertex Shader"), WINDOW_WIDTH, WINDOW_HEIGHT, ES_WINDOW_RGB | ES_WINDOW_POST_SUB_BUFFER_SUPPORTED );
if ( !Init ( &esContext ) )
return 0;
esRegisterDrawFunc ( &esContext, Draw );
esRegisterUpdateFunc ( &esContext, Update );
esMainLoop ( &esContext );
ShutDown ( &esContext );
}
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="PostSubBuffer"
ProjectGUID="{667CE95F-5DD8-4495-8C18-5CA8A175B12D}"
RootNamespace="Simple_VertexShader"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../Common;../../../include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
AdditionalLibraryDirectories=""
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
EmbedManifest="true"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="0"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../Common;../../../include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
AdditionalLibraryDirectories=""
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\PostSubBuffer.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
...@@ -73,6 +73,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "essl_to_hlsl", "translator\ ...@@ -73,6 +73,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "essl_to_hlsl", "translator\
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "translator_common", "..\src\compiler\translator_common.vcproj", "{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "translator_common", "..\src\compiler\translator_common.vcproj", "{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PostSubBuffer", "gles2_book\PostSubBuffer\PostSubBuffer.vcproj", "{667CE95F-5DD8-4495-8C18-5CA8A175B12D}"
ProjectSection(ProjectDependencies) = postProject
{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F} = {47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
...@@ -139,6 +144,10 @@ Global ...@@ -139,6 +144,10 @@ Global
{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.Build.0 = Debug|Win32 {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.Build.0 = Debug|Win32
{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.ActiveCfg = Release|Win32 {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.ActiveCfg = Release|Win32
{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.Build.0 = Release|Win32 {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.Build.0 = Release|Win32
{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Debug|Win32.ActiveCfg = Debug|Win32
{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Debug|Win32.Build.0 = Debug|Win32
{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Release|Win32.ActiveCfg = Release|Win32
{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
......
...@@ -503,6 +503,7 @@ bool Display::resetDevice() ...@@ -503,6 +503,7 @@ bool Display::resetDevice()
EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
{ {
const Config *configuration = mConfigSet.get(config); const Config *configuration = mConfigSet.get(config);
EGLint postSubBufferSupported = EGL_FALSE;
if (attribList) if (attribList)
{ {
...@@ -521,6 +522,9 @@ EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGL ...@@ -521,6 +522,9 @@ EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGL
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
} }
break; break;
case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
postSubBufferSupported = attribList[1];
break;
case EGL_VG_COLORSPACE: case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE); return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
case EGL_VG_ALPHA_FORMAT: case EGL_VG_ALPHA_FORMAT:
...@@ -544,7 +548,7 @@ EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGL ...@@ -544,7 +548,7 @@ EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGL
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
Surface *surface = new Surface(this, configuration, window); Surface *surface = new Surface(this, configuration, window, postSubBufferSupported);
if (!surface->initialize()) if (!surface->initialize())
{ {
...@@ -1039,7 +1043,8 @@ void Display::initExtensionString() ...@@ -1039,7 +1043,8 @@ void Display::initExtensionString()
mExtensionString += "EGL_EXT_create_context_robustness "; mExtensionString += "EGL_EXT_create_context_robustness ";
// ANGLE-specific extensions // ANGLE-specific extensions
if (isd3d9ex) { if (isd3d9ex)
{
mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer "; mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
} }
...@@ -1047,13 +1052,16 @@ void Display::initExtensionString() ...@@ -1047,13 +1052,16 @@ void Display::initExtensionString()
if (swiftShader) if (swiftShader)
{ {
mExtensionString += "EGL_ANGLE_software_display "; mExtensionString += "EGL_ANGLE_software_display ";
} }
if (isd3d9ex) { if (isd3d9ex)
{
mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle "; mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle ";
} }
mExtensionString += "EGL_NV_post_sub_buffer";
std::string::size_type end = mExtensionString.find_last_not_of(' '); std::string::size_type end = mExtensionString.find_last_not_of(' ');
if (end != std::string::npos) if (end != std::string::npos)
{ {
......
...@@ -39,8 +39,8 @@ int getComparableOSVersion() ...@@ -39,8 +39,8 @@ int getComparableOSVersion()
} }
} }
Surface::Surface(Display *display, const Config *config, HWND window) Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported)
: mDisplay(display), mConfig(config), mWindow(window) : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
{ {
mSwapChain = NULL; mSwapChain = NULL;
mDepthStencil = NULL; mDepthStencil = NULL;
...@@ -61,7 +61,7 @@ Surface::Surface(Display *display, const Config *config, HWND window) ...@@ -61,7 +61,7 @@ Surface::Surface(Display *display, const Config *config, HWND window)
} }
Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
: mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height) : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{ {
mSwapChain = NULL; mSwapChain = NULL;
mDepthStencil = NULL; mDepthStencil = NULL;
...@@ -174,6 +174,13 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) ...@@ -174,6 +174,13 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
return false; return false;
} }
IDirect3DSurface9* preservedRenderTarget = NULL;
if (mPostSubBufferSupported && mRenderTarget)
{
preservedRenderTarget = mRenderTarget;
preservedRenderTarget->AddRef();
}
// Evict all non-render target textures to system memory and release all resources // Evict all non-render target textures to system memory and release all resources
// before reallocating them to free up as much video memory as possible. // before reallocating them to free up as much video memory as possible.
device->EvictManagedResources(); device->EvictManagedResources();
...@@ -212,6 +219,12 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) ...@@ -212,6 +219,12 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
useFlipEx = false; useFlipEx = false;
} }
// D3DSWAPEFFECT_FLIPEX does not preserve the back buffer.
if (mPostSubBufferSupported)
{
useFlipEx = false;
}
presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat; presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
// We set BackBufferCount = 1 even when we use D3DSWAPEFFECT_FLIPEX. // We set BackBufferCount = 1 even when we use D3DSWAPEFFECT_FLIPEX.
// We do this because DirectX docs are a bit vague whether to set this to 1 // We do this because DirectX docs are a bit vague whether to set this to 1
...@@ -230,7 +243,7 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) ...@@ -230,7 +243,7 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
if(useFlipEx) if(useFlipEx)
presentParameters.SwapEffect = D3DSWAPEFFECT_FLIPEX; presentParameters.SwapEffect = D3DSWAPEFFECT_FLIPEX;
else else
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; presentParameters.SwapEffect = mPostSubBufferSupported ? D3DSWAPEFFECT_COPY : D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE; presentParameters.Windowed = TRUE;
presentParameters.BackBufferWidth = backbufferWidth; presentParameters.BackBufferWidth = backbufferWidth;
presentParameters.BackBufferHeight = backbufferHeight; presentParameters.BackBufferHeight = backbufferHeight;
...@@ -255,6 +268,13 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) ...@@ -255,6 +268,13 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
release(); release();
if (preservedRenderTarget)
{
preservedRenderTarget->Release();
preservedRenderTarget = NULL;
}
if(isDeviceLostError(result)) if(isDeviceLostError(result))
{ {
mDisplay->notifyDeviceLost(); mDisplay->notifyDeviceLost();
...@@ -266,6 +286,44 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) ...@@ -266,6 +286,44 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
} }
} }
if (mWindow)
{
mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget);
if (!preservedRenderTarget)
{
InvalidateRect(mWindow, NULL, FALSE);
}
}
else
{
mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
}
if (preservedRenderTarget)
{
RECT rect =
{
0, 0,
mWidth, mHeight
};
if (rect.right > static_cast<LONG>(presentParameters.BackBufferWidth))
{
rect.right = presentParameters.BackBufferWidth;
}
if (rect.bottom > static_cast<LONG>(presentParameters.BackBufferHeight))
{
rect.bottom = presentParameters.BackBufferHeight;
}
mDisplay->endScene();
device->StretchRect(preservedRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
preservedRenderTarget->Release();
preservedRenderTarget = NULL;
}
if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN) if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
{ {
result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
...@@ -282,13 +340,6 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) ...@@ -282,13 +340,6 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
return error(EGL_BAD_ALLOC, false); return error(EGL_BAD_ALLOC, false);
} }
if (mWindow) {
mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget);
InvalidateRect(mWindow, NULL, FALSE);
} else {
mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
}
mWidth = presentParameters.BackBufferWidth; mWidth = presentParameters.BackBufferWidth;
mHeight = presentParameters.BackBufferHeight; mHeight = presentParameters.BackBufferHeight;
...@@ -441,6 +492,64 @@ bool Surface::swap() ...@@ -441,6 +492,64 @@ bool Surface::swap()
return true; return true;
} }
bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (x < 0 || y < 0 || width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, false);
}
if (!mPostSubBufferSupported)
{
// Spec is not clear about how this should be handled.
return true;
}
if (mSwapChain)
{
mDisplay->endScene();
RECT rect =
{
x, mHeight - y - height,
x + width, mHeight - y
};
if (rect.right > mWidth)
{
rect.right = mWidth;
}
if (rect.bottom > mHeight)
{
rect.bottom = mHeight;
}
if (rect.left == rect.right || rect.top == rect.bottom)
{
return true;
}
HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
{
return error(EGL_BAD_ALLOC, false);
}
if (result == D3DERR_DEVICELOST || result == D3DERR_DEVICEHUNG || result == D3DERR_DEVICEREMOVED)
{
return error(EGL_CONTEXT_LOST, false);
}
ASSERT(SUCCEEDED(result));
checkForOutOfDateSwapChain();
}
return true;
}
EGLint Surface::getWidth() const EGLint Surface::getWidth() const
{ {
return mWidth; return mWidth;
...@@ -451,6 +560,11 @@ EGLint Surface::getHeight() const ...@@ -451,6 +560,11 @@ EGLint Surface::getHeight() const
return mHeight; return mHeight;
} }
EGLint Surface::isPostSubBufferSupported() const
{
return mPostSubBufferSupported;
}
IDirect3DSurface9 *Surface::getRenderTarget() IDirect3DSurface9 *Surface::getRenderTarget()
{ {
if (mRenderTarget) if (mRenderTarget)
......
...@@ -30,7 +30,7 @@ class Config; ...@@ -30,7 +30,7 @@ class Config;
class Surface class Surface
{ {
public: public:
Surface(Display *display, const egl::Config *config, HWND window); Surface(Display *display, const egl::Config *config, HWND window, EGLint postSubBufferSupported);
Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
~Surface(); ~Surface();
...@@ -41,10 +41,13 @@ class Surface ...@@ -41,10 +41,13 @@ class Surface
HWND getWindowHandle(); HWND getWindowHandle();
bool swap(); bool swap();
bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
virtual EGLint getWidth() const; virtual EGLint getWidth() const;
virtual EGLint getHeight() const; virtual EGLint getHeight() const;
virtual EGLint isPostSubBufferSupported() const;
virtual IDirect3DSurface9 *getRenderTarget(); virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil(); virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture(); virtual IDirect3DTexture9 *getOffscreenTexture();
...@@ -96,6 +99,8 @@ private: ...@@ -96,6 +99,8 @@ private:
// EGLenum vgAlphaFormat; // Alpha format for OpenVG // EGLenum vgAlphaFormat; // Alpha format for OpenVG
// EGLenum vgColorSpace; // Color space for OpenVG // EGLenum vgColorSpace; // Color space for OpenVG
EGLint mSwapInterval; EGLint mSwapInterval;
EGLint mPostSubBufferSupported;
DWORD mPresentInterval; DWORD mPresentInterval;
bool mPresentIntervalDirty; bool mPresentIntervalDirty;
gl::Texture2D *mTexture; gl::Texture2D *mTexture;
......
...@@ -488,6 +488,9 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint ...@@ -488,6 +488,9 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
case EGL_WIDTH: case EGL_WIDTH:
*value = eglSurface->getWidth(); *value = eglSurface->getWidth();
break; break;
case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
*value = eglSurface->isPostSubBufferSupported();
break;
default: default:
return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
} }
...@@ -1166,6 +1169,43 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ ...@@ -1166,6 +1169,43 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ
return EGL_FALSE; return EGL_FALSE;
} }
EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
if (display->isDeviceLost())
{
return error(EGL_CONTEXT_LOST, EGL_FALSE);
}
if (surface == EGL_NO_SURFACE)
{
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
if (eglSurface->postSubBuffer(x, y, width, height))
{
return success(EGL_TRUE);
}
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_FALSE);
}
return EGL_FALSE;
}
__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname) __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
{ {
EVENT("(const char *procname = \"%s\")", procname); EVENT("(const char *procname = \"%s\")", procname);
...@@ -1181,6 +1221,7 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char ...@@ -1181,6 +1221,7 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char
static const Extension eglExtensions[] = static const Extension eglExtensions[] =
{ {
{"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE}, {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
{"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV},
{"", NULL}, {"", NULL},
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment