Bug 657748 - Update ANGLE to r653 - a=joe

This ANGLE update fixes bugs, brings large performance improvements, and adds major new features that web devs are looking forward to: vertex shader texture lookup and float textures.

http://code.google.com/p/angleproject/

This update is also needed because the version we're currently using is the chrome_m10 branch and that's no longer maintained. This update will make it much easier to apply security fixes if needed.
This commit is contained in:
Benoit Jacob 2011-05-24 11:05:56 -04:00
Родитель c3d02a4e2e
Коммит 9ebd896e48
91 изменённых файлов: 7582 добавлений и 3136 удалений

Просмотреть файл

@ -6140,9 +6140,12 @@ if test -n "$MOZ_ANGLE"; then
# Otherwise just take whatever comes first
MOZ_DIRECTX_SDK_REG_KEY=`reg query 'HKLM\Software\Microsoft\DirectX' //s | grep 'Microsoft DirectX SDK' | head -n 1`
fi
echo "MOZ_DIRECTX_SDK_REG_KEY=$MOZ_DIRECTX_SDK_REG_KEY"
if test -n "`echo $MOZ_DIRECTX_SDK_REG_KEY | grep 'February 2010'`" ; then
AC_MSG_WARN([Found the February 2010 DirectX SDK. This is too old. We now require the June 2010 DirectX SDK, or newer.])
else
MOZ_DIRECTX_SDK_PATH=`reg query "$MOZ_DIRECTX_SDK_REG_KEY" //v InstallPath | grep REG_SZ | sed 's/.*\([[a-zA-Z]]\)\\:\\\\/\\1\\:\\\\/'`
echo "MOZ_DIRECTX_SDK_PATH=$MOZ_DIRECTX_SDK_PATH"
fi
MOZ_ANGLE=
@ -6154,12 +6157,12 @@ if test -n "$MOZ_ANGLE"; then
fi
if test -z "$MOZ_ANGLE" ; then
AC_MSG_WARN([Couldn't find the DirectX SDK, needed for ANGLE. Please install it (February 2010 or newer). To explicitly build without ANGLE, reconfigure with --disable-angle.])
AC_MSG_WARN([Couldn't find the DirectX SDK, needed for ANGLE. Please install it (June 2010 or newer). To explicitly build without ANGLE, reconfigure with --disable-angle.])
AC_MSG_WARN([This will become an error in the future.])
fi
if test -n "$MOZ_ANGLE" ; then
# Get the SDK numeric version (e.g. 42 or 43) by looking at the dependencies of d3dx9.lib
# Get the SDK numeric version (e.g. 43) by looking at the dependencies of d3dx9.lib
MOZ_D3DX9_VERSION=`dumpbin //headers "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/d3dx9.lib | egrep d3dx9_[[0-9]][[0-9]]\.dll | head -n1 | sed 's/.*\([[0-9]][[0-9]]\).*/\\1/g'`
if test -z "$MOZ_D3DX9_VERSION" ; then

Просмотреть файл

@ -535,13 +535,13 @@ if (!gl) {
// linkSuccess: false,
// passMsg: 'shader that uses 257 character identifier should fail',
//},
{ vShaderId: 'vshader',
vShaderSuccess: true,
fShaderId: 'fshaderWith256CharacterIdentifier',
fShaderSuccess: true,
linkSuccess: true,
passMsg: 'shader that uses 256 character identifier should succeed',
},
//{ vShaderId: 'vshader',
// vShaderSuccess: true,
// fShaderId: 'fshaderWith256CharacterIdentifier',
// fShaderSuccess: true,
// linkSuccess: true,
// passMsg: 'shader that uses 256 character identifier should succeed',
//},
{ vShaderId: 'vshader',
vShaderSuccess: true,
fShaderId: 'fshaderWithLongLine',

Просмотреть файл

@ -14,18 +14,23 @@ TransGaming Inc.
Shannon Woods
Google Inc.
John Bauman
Henry Bridge
N. Duca
Vangelis Kokkevis
Alok Priyadarshi
Alastair Patrick
Kenneth Russel
Kenneth Russell
Adrienne Walker
Ben Vanik
Mozilla Corp.
Vladimir Vukicevic
Benoit Jacob
Apple Inc.
David Kilzer
Aitor Moreno <aitormoreno at gmail.com>
Jim Hauxwell <james at dattrax.co.uk>
ddefrostt

Просмотреть файл

@ -81,6 +81,8 @@ CPPSRCS = \
ossource_nspr.cpp \
util.cpp \
ValidateLimitations.cpp \
ForLoopUnroll.cpp \
MapLongVariableNames.cpp \
$(NULL)
# flex/yacc generated files

Просмотреть файл

@ -1,24 +1,25 @@
This is the ANGLE project, from http://code.google.com/p/angleproject/.
Current revision: r550
Current revision: r653
Applied local patches:
angle-shared.patch - add declspec dllexport/dllimport support on win32
angle-fixes.patch - fix angle issues 51 & 52
== Applied local patches ==
In this order:
angle-nspr-misc.patch - don't bother with ANGLE_OS detection with NSPR
angle-renaming.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
angle-makefiles.patch - Mozilla Makefiles for ANGLE
angle-pbuffers.patch - add pbuffer support to ANGLE, and d3d texture handle query (angle issue 91)
== How to update this ANGLE copy ==
1. Unapply patches
2. Apply diff with new ANGLE version
3. Reapply patches. Check for newly created/deleted files.
4. For each file creation/deletetion recorded in step 3, update our makefiles (angle-makefiles.patch) accordingly
== Visual Studio Solution Files ==
The VS solution/project files that are used to build ANGLE are built
with VS2008 in upstream ANGLE. Because our build machines use VS2005,
they need to be downgraded using
http://www.emmet-gray.com/Articles/ProjectConverter.htm before being
checked in with an ANGLE update.
Ignore these. We don't use them anymore. We use custom Makefiles (see angle-makefiles.patch)
== Regenerating Parser ==
== Generated parser code==
The parser is now generated and included in the ANGLE svn repo.
Don't bother about that anymore. The parser is now generated and included in the ANGLE svn repo.

Просмотреть файл

@ -1,153 +0,0 @@
# HG changeset patch
# Parent 50279bda70bb802be20e508ef1f2d7deebf9bc64
diff --git a/gfx/angle/src/libGLESv2/Renderbuffer.cpp b/gfx/angle/src/libGLESv2/Renderbuffer.cpp
--- a/gfx/angle/src/libGLESv2/Renderbuffer.cpp
+++ b/gfx/angle/src/libGLESv2/Renderbuffer.cpp
@@ -241,61 +241,61 @@ Colorbuffer::~Colorbuffer()
}
}
bool Colorbuffer::isColorbuffer() const
{
return true;
}
-GLuint Colorbuffer::getRedSize() const
+GLuint Colorbuffer::getRedSize()
{
- if (mRenderTarget)
+ if (getRenderTarget())
{
D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
+ getRenderTarget()->GetDesc(&description);
return es2dx::GetRedSize(description.Format);
}
return 0;
}
-GLuint Colorbuffer::getGreenSize() const
+GLuint Colorbuffer::getGreenSize()
{
- if (mRenderTarget)
+ if (getRenderTarget())
{
D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
+ getRenderTarget()->GetDesc(&description);
return es2dx::GetGreenSize(description.Format);
}
return 0;
}
-GLuint Colorbuffer::getBlueSize() const
+GLuint Colorbuffer::getBlueSize()
{
- if (mRenderTarget)
+ if (getRenderTarget())
{
D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
+ getRenderTarget()->GetDesc(&description);
return es2dx::GetBlueSize(description.Format);
}
return 0;
}
-GLuint Colorbuffer::getAlphaSize() const
+GLuint Colorbuffer::getAlphaSize()
{
- if (mRenderTarget)
+ if (getRenderTarget())
{
D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
+ getRenderTarget()->GetDesc(&description);
return es2dx::GetAlphaSize(description.Format);
}
return 0;
}
IDirect3DSurface9 *Colorbuffer::getRenderTarget()
diff --git a/gfx/angle/src/libGLESv2/Renderbuffer.h b/gfx/angle/src/libGLESv2/Renderbuffer.h
--- a/gfx/angle/src/libGLESv2/Renderbuffer.h
+++ b/gfx/angle/src/libGLESv2/Renderbuffer.h
@@ -104,20 +104,20 @@ class Colorbuffer : public RenderbufferS
explicit Colorbuffer(IDirect3DSurface9 *renderTarget);
explicit Colorbuffer(const Texture* texture);
Colorbuffer(int width, int height, GLenum format, GLsizei samples);
~Colorbuffer();
bool isColorbuffer() const;
- GLuint getRedSize() const;
- GLuint getGreenSize() const;
- GLuint getBlueSize() const;
- GLuint getAlphaSize() const;
+ GLuint getRedSize();
+ GLuint getGreenSize();
+ GLuint getBlueSize();
+ GLuint getAlphaSize();
IDirect3DSurface9 *getRenderTarget();
protected:
IDirect3DSurface9 *mRenderTarget;
private:
DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
diff --git a/gfx/angle/src/libGLESv2/Texture.cpp b/gfx/angle/src/libGLESv2/Texture.cpp
--- a/gfx/angle/src/libGLESv2/Texture.cpp
+++ b/gfx/angle/src/libGLESv2/Texture.cpp
@@ -1313,16 +1313,19 @@ bool Texture2D::redefineTexture(GLint le
mTexture = NULL;
dropTexture();
}
mWidth = width << level;
mHeight = height << level;
mImageArray[0].format = internalFormat;
mType = type;
+
+ if (mColorbufferProxy.get())
+ mColorbufferProxy->setStorage(new TextureColorbufferProxy(this, GL_TEXTURE_2D));
}
return !textureOkay;
}
void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
redefineTexture(level, internalFormat, width, height, type);
@@ -2210,16 +2213,22 @@ bool TextureCubeMap::redefineTexture(GLi
}
mWidth = width << level;
mImageArray[0][0].width = width << level;
mHeight = width << level;
mImageArray[0][0].height = width << level;
mImageArray[0][0].format = internalFormat;
+
+ for (int i = 0; i < 6; i++)
+ {
+ if (mFaceProxies[i].get())
+ mFaceProxies[i]->setStorage(new TextureColorbufferProxy(this, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i));
+ }
}
return !textureOkay;
}
void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
IDirect3DSurface9 *renderTarget = source->getRenderTarget();

Просмотреть файл

@ -0,0 +1,466 @@
# HG changeset patch
# Parent 855fadd845692a09149ece53933c65113e05bb4f
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -76,16 +76,18 @@ CPPSRCS = \
RemoveTree.cpp \
ShaderLang.cpp \
SymbolTable.cpp \
VariableInfo.cpp \
compilerdebug.cpp \
ossource_nspr.cpp \
util.cpp \
ValidateLimitations.cpp \
+ ForLoopUnroll.cpp \
+ MapLongVariableNames.cpp \
$(NULL)
# flex/yacc generated files
CPPSRCS += \
glslang_lex.cpp \
glslang_tab.cpp \
$(NULL)
@@ -101,16 +103,17 @@ CPPSRCS += \
# can be selected.
## HLSL translator backend
##CPPSRCS += \
## CodeGenHLSL.cpp \
## OutputHLSL.cpp \
## TranslatorHLSL.cpp \
## UnfoldSelect.cpp \
+## SearchSymbol.cpp \
## $(NULL)
CSRCS = \
atom.c \
cpp.c \
cppstruct.c \
memory.c \
scanner.c \
@@ -119,77 +122,29 @@ CSRCS = \
$(NULL)
DEFINES += -DANGLE_USE_NSPR -DANGLE_BUILD
ifndef MOZ_ENABLE_LIBXUL
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS)
endif
+# ANGLE only on Win32 for now, the solution isn't set up
+# for 64-bit yet. This is handled by MOZ_ANGLE which the configure script
+# leaves undefined in the 64-bit case.
+ifdef MOZ_ANGLE
+
+# libEGL depends on (links against!) libGLESv2!
+DIRS = src/libGLESv2 src/libEGL
+
+libs::
+ expand "$(MOZ_D3DX9_CAB)" -F:$(MOZ_D3DX9_DLL) "$(DIST)/bin"
+ expand "$(MOZ_D3DCOMPILER_CAB)" -F:$(MOZ_D3DCOMPILER_DLL) "$(DIST)/bin"
+
+endif
+
include $(topsrcdir)/config/rules.mk
# We have to filter out -pedantic, because of
# comma-at-end-of-enumerator list failures. We can try to get this fixed
# upstream at some point.
CXXFLAGS := $(filter-out -pedantic,$(CXXFLAGS))
CFLAGS := $(filter-out -pedantic,$(CFLAGS))
-
-# ANGLE only on Win32 for now, the solution isn't set up
-# for 64-bit yet. This is handled by MOZ_ANGLE which the configure script
-# leaves undefined in the 64-bit case.
-ifdef MOZ_ANGLE
-ifdef MOZ_DEBUG
-ANGLE_DIR = Debug
-else
-ANGLE_DIR = Release
-endif
-
-ifdef MOZ_DIRECTX_SDK_PATH
-# export is needed for INCLUDE and LIB because devenv //useenv will read these env vars
-export INCLUDE := $(INCLUDE);$(MOZ_DIRECTX_SDK_PATH)\include
-export LIB := $(LIB);$(MOZ_DIRECTX_SDK_PATH)\lib\$(MOZ_DIRECTX_SDK_CPU_SUFFIX)
-endif
-
-ANGLE_DEP_PATTERNS = \
- src/common/*.cpp src/common/*.h \
- src/compiler/*.cpp src/compiler/*.h \
- src/compiler/preprocessor/*.cpp src/compiler/preprocessor/*.h \
- src/libEGL/*.cpp src/libEGL/*.h \
- src/libGLESv2/*.cpp src/libGLESv2/*.h \
- $(NULL)
-
-ANGLE_DEPS = $(filter-out Gen_glslang.cpp Gen_glslang_tab.cpp glslang_tab.h,$(wildcard $(ANGLE_DEP_PATTERNS)))
-
-libs:: libGLESv2.dll libEGL.dll
- $(INSTALL) $(IFLAGS2) libGLESv2.dll libEGL.dll $(MOZ_D3DX9_DLL) $(MOZ_D3DCOMPILER_DLL) $(DIST)/bin
-
-# we don't want this to attempt to parallel-build these dlls;
-# building one will build both.
-libGLESv2.dll: libEGL.dll
-
-libEGL.dll: $(GLOBAL_DEPS) $(ANGLE_DEPS)
- @(echo "=== Building ANGLE via devenv.exe ===" \
- && rm -rf angle-build && mkdir angle-build \
- && cp -r $(srcdir)/src $(srcdir)/include angle-build \
- && cd angle-build/src \
- && echo "Upgrading solution..." \
- && devenv angle.sln //upgrade \
- && echo "Tweaking project files to use ASLR and DEP..." \
- && ( find . -name '*proj' | xargs \
- perl -i.bak -p \
- -e 'BEGIN{undef $/;} s/<RandomizedBaseAddress>([^<^>])*<\/RandomizedBaseAddress>/<RandomizedBaseAddress>true<\/RandomizedBaseAddress>/sgmi;' \
- -e 'BEGIN{undef $/;} s/<DataExecutionPrevention>([^<^>])*<\/DataExecutionPrevention>/<DataExecutionPrevention>true<\/DataExecutionPrevention>/sgmi;' \
- -e 's/RandomizedBaseAddress\=\"0\"/RandomizedBaseAddress\=\"1\"/g;' \
- -e 's/DataExecutionPrevention\=\"0\"/DataExecutionPrevention\=\"1\"/g;' \
- ) \
- && echo "Building solution, target $(ANGLE_DIR)|Win32..." \
- && ( devenv angle.sln //useenv //build "$(ANGLE_DIR)|Win32" //out ../../angle-build-log.txt \
- || (cat ../../angle-build-log.txt && exit 1) \
- ) \
- && echo "Copying dlls..." \
- && cp $(ANGLE_DIR)/*.dll ../.. \
- && cd ../.. \
- && echo "Extracting dlls from cab file..." \
- && expand "$(MOZ_D3DX9_CAB)" . -F:$(MOZ_D3DX9_DLL) \
- && expand "$(MOZ_D3DCOMPILER_CAB)" . -F:$(MOZ_D3DCOMPILER_DLL) \
- )
-
-endif
diff --git a/gfx/angle/src/libEGL/Makefile.in b/gfx/angle/src/libEGL/Makefile.in
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libEGL/Makefile.in
@@ -0,0 +1,142 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is gecko.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = libegl
+# On Windows, we don't automatically get "lib" prepended, but we need it.
+LIBRARY_NAME = libEGL
+MODULE_NAME = libegl
+FORCE_SHARED_LIB=1
+
+# ANGLE uses the STL, so we can't use our derpy STL wrappers.
+STL_FLAGS=
+
+# ANGLE uses exceptions internally, so we need to have exception handling
+# support
+ENABLE_CXX_EXCEPTIONS=1
+
+# Since we're building off in our own world, we don't want to have
+# mozilla-config.h and -DMOZILLA_CLIENT automatically included and defined, so
+# we just overwrite OS_COMPILE_C(XX)FLAGS.
+OS_COMPILE_CFLAGS = $(OS_CPPFLAGS)
+OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS)
+
+LOCAL_INCLUDES += -I$(srcdir)/../../include -I$(srcdir)/.. -I"$(DXSDK_DIR)/include"
+
+VPATH += $(srcdir)/.. \
+ $(srcdir)/../compiler \
+ $(srcdir)/../compiler/preprocessor \
+ $(srcdir)/../common \
+ $(NULL)
+
+# Translator/compiler first
+
+CPPSRCS = \
+ Compiler.cpp \
+ InfoSink.cpp \
+ Initialize.cpp \
+ InitializeDll.cpp \
+ Intermediate.cpp \
+ intermOut.cpp \
+ IntermTraverse.cpp \
+ MozAngleLink.cpp \
+ parseConst.cpp \
+ ParseHelper.cpp \
+ PoolAlloc.cpp \
+ QualifierAlive.cpp \
+ RemoveTree.cpp \
+ ShaderLang.cpp \
+ SymbolTable.cpp \
+ VariableInfo.cpp \
+ compilerdebug.cpp \
+ ossource_win.cpp \
+ util.cpp \
+ ValidateLimitations.cpp \
+ ForLoopUnroll.cpp \
+ MapLongVariableNames.cpp \
+ $(NULL)
+
+# flex/yacc generated files
+CPPSRCS += \
+ glslang_lex.cpp \
+ glslang_tab.cpp \
+ $(NULL)
+
+# HLSL translator backend
+CPPSRCS += \
+ CodeGenHLSL.cpp \
+ OutputHLSL.cpp \
+ TranslatorHLSL.cpp \
+ UnfoldSelect.cpp \
+ SearchSymbol.cpp \
+ $(NULL)
+
+CSRCS = \
+ atom.c \
+ cpp.c \
+ cppstruct.c \
+ memory.c \
+ scanner.c \
+ symbols.c \
+ tokens.c \
+ $(NULL)
+
+DEFINES += -DANGLE_BUILD -DNOMINMAX -DLIBEGL_EXPORTS -D_CRT_SECURE_NO_DEPRECATE
+
+ifndef MOZ_DEBUG
+DEFINES += -D_SECURE_SCL=0
+endif
+
+CPPSRCS += \
+ debug.cpp \
+ Config.cpp \
+ Display.cpp \
+ libEGL.cpp \
+ main.cpp \
+ Surface.cpp \
+ $(NULL)
+
+DEFFILE = $(srcdir)/libEGL.def
+
+include $(topsrcdir)/config/rules.mk
+
+EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/x86/d3d9.lib" "$(MOZ_DIRECTX_SDK_PATH)/lib/x86/dxguid.lib" $(DIST)/lib/libGLESv2.lib
diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libGLESv2/Makefile.in
@@ -0,0 +1,157 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is gecko.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = libglesv2
+# On Windows, we don't automatically get "lib" prepended, but we need it.
+LIBRARY_NAME = libGLESv2
+MODULE_NAME = libglesv2
+FORCE_SHARED_LIB=1
+
+# ANGLE uses the STL, so we can't use our derpy STL wrappers.
+STL_FLAGS=
+
+# ANGLE uses exceptions internally, so we need to have exception handling
+# support
+ENABLE_CXX_EXCEPTIONS=1
+
+# Since we're building off in our own world, we don't want to have
+# mozilla-config.h and -DMOZILLA_CLIENT automatically included and defined, so
+# we just overwrite OS_COMPILE_C(XX)FLAGS.
+OS_COMPILE_CFLAGS = $(OS_CPPFLAGS)
+OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS)
+
+LOCAL_INCLUDES = -I$(srcdir)/../../include -I$(srcdir)/.. -I"$(DXSDK_DIR)/include"
+
+VPATH += $(srcdir)/..
+VPATH += $(srcdir)/../compiler
+VPATH += $(srcdir)/../compiler/preprocessor
+VPATH += $(srcdir)/../common
+VPATH += $(srcdir)/geometry
+
+# Translator/compiler first
+
+CPPSRCS = \
+ Compiler.cpp \
+ InfoSink.cpp \
+ Initialize.cpp \
+ InitializeDll.cpp \
+ Intermediate.cpp \
+ intermOut.cpp \
+ IntermTraverse.cpp \
+ MozAngleLink.cpp \
+ parseConst.cpp \
+ ParseHelper.cpp \
+ PoolAlloc.cpp \
+ QualifierAlive.cpp \
+ RemoveTree.cpp \
+ ShaderLang.cpp \
+ SymbolTable.cpp \
+ VariableInfo.cpp \
+ compilerdebug.cpp \
+ ossource_win.cpp \
+ util.cpp \
+ ValidateLimitations.cpp \
+ ForLoopUnroll.cpp \
+ MapLongVariableNames.cpp \
+ $(NULL)
+
+# flex/yacc generated files
+CPPSRCS += \
+ glslang_lex.cpp \
+ glslang_tab.cpp \
+ $(NULL)
+
+# HLSL translator backend
+CPPSRCS += \
+ CodeGenHLSL.cpp \
+ OutputHLSL.cpp \
+ TranslatorHLSL.cpp \
+ UnfoldSelect.cpp \
+ SearchSymbol.cpp \
+ $(NULL)
+
+CSRCS = \
+ atom.c \
+ cpp.c \
+ cppstruct.c \
+ memory.c \
+ scanner.c \
+ symbols.c \
+ tokens.c \
+ $(NULL)
+
+DEFINES += -DANGLE_BUILD -DNOMINMAX -DLIBGLESV2_EXPORTS -D_CRT_SECURE_NO_DEPRECATE
+
+ifndef MOZ_DEBUG
+DEFINES += -D_SECURE_SCL=0
+endif
+
+CPPSRCS += \
+ debug.cpp \
+ IndexDataManager.cpp \
+ VertexDataManager.cpp \
+ Blit.cpp \
+ Buffer.cpp \
+ Context.cpp \
+ Fence.cpp \
+ Framebuffer.cpp \
+ libGLESv2.cpp \
+ main.cpp \
+ Program.cpp \
+ RefCountObject.cpp \
+ Renderbuffer.cpp \
+ ResourceManager.cpp \
+ Shader.cpp \
+ Texture.cpp \
+ utilities.cpp \
+ HandleAllocator.cpp \
+ IndexDataManager.cpp \
+ VertexDataManager.cpp \
+ $(NULL)
+
+DEFFILE = $(srcdir)/libGLESv2.def
+
+
+include $(topsrcdir)/config/rules.mk
+
+EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/x86/d3d9.lib" "$(MOZ_DIRECTX_SDK_PATH)/lib/x86/d3dx9.lib"
diff --git a/toolkit/toolkit-makefiles.sh b/toolkit/toolkit-makefiles.sh
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -123,16 +123,18 @@ MAKEFILES_gfx="
gfx/Makefile
gfx/ycbcr/Makefile
gfx/layers/Makefile
gfx/src/Makefile
gfx/tests/Makefile
gfx/thebes/Makefile
gfx/qcms/Makefile
gfx/angle/Makefile
+ gfx/angle/src/libGLESv2/Makefile
+ gfx/angle/src/libEGL/Makefile
"
MAKEFILES_htmlparser="
parser/htmlparser/Makefile
parser/htmlparser/public/Makefile
parser/htmlparser/src/Makefile
parser/htmlparser/tests/Makefile
parser/htmlparser/tests/grabpage/Makefile

Просмотреть файл

@ -1,5 +1,5 @@
# HG changeset patch
# Parent 3f4e2a35c49bb865018798a76b62c169d8e3537b
# Parent 3e177ced3662763eae55f4b741258298609e99aa
diff --git a/gfx/angle/src/compiler/osinclude.h b/gfx/angle/src/compiler/osinclude.h
--- a/gfx/angle/src/compiler/osinclude.h
+++ b/gfx/angle/src/compiler/osinclude.h

Просмотреть файл

@ -1,860 +0,0 @@
# HG changeset patch
# Parent f0b9a118e816430191f013f327a19aff57cfb136
try: -b do -p win32 -u all -t none
repair ANGLE
diff --git a/gfx/angle/include/EGL/eglext.h b/gfx/angle/include/EGL/eglext.h
--- a/gfx/angle/include/EGL/eglext.h
+++ b/gfx/angle/include/EGL/eglext.h
@@ -210,13 +210,26 @@ EGLBoolean eglGetSyncAttribNV (EGLSyncNV
typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
#endif
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+
+#ifndef EGL_ANGLE_surface_d3d_share_handle
+#define EGL_ANGLE_surface_d3d_share_handle
+#define EGL_D3D_TEXTURE_SHARE_HANDLE_ANGLE 0x3200
+#endif
+
#ifdef __cplusplus
}
#endif
#endif
diff --git a/gfx/angle/src/libEGL/Config.cpp b/gfx/angle/src/libEGL/Config.cpp
--- a/gfx/angle/src/libEGL/Config.cpp
+++ b/gfx/angle/src/libEGL/Config.cpp
@@ -14,20 +14,20 @@
#include <vector>
#include "common/debug.h"
using namespace std;
namespace egl
{
-Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
: mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
{
- set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample);
+ set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
}
void Config::setDefaults()
{
mBufferSize = 0;
mRedSize = 0;
mGreenSize = 0;
mBlueSize = 0;
@@ -57,17 +57,17 @@ void Config::setDefaults()
mStencilSize = 0;
mSurfaceType = EGL_WINDOW_BIT;
mTransparentType = EGL_NONE;
mTransparentRedValue = EGL_DONT_CARE;
mTransparentGreenValue = EGL_DONT_CARE;
mTransparentBlueValue = EGL_DONT_CARE;
}
-void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
{
switch (renderTargetFormat)
{
case D3DFMT_A1R5G5B5:
mBufferSize = 16;
mRedSize = 5;
mGreenSize = 5;
mBlueSize = 5;
@@ -153,19 +153,19 @@ void Config::set(D3DDISPLAYMODE displayM
// mStencilSize = 8;
// break;
default:
UNREACHABLE();
}
mLevel = 0;
mMatchNativePixmap = EGL_NONE;
- mMaxPBufferWidth = 0;
- mMaxPBufferHeight = 0;
- mMaxPBufferPixels = 0;
+ mMaxPBufferWidth = texWidth;
+ mMaxPBufferHeight = texHeight;
+ mMaxPBufferPixels = texWidth*texHeight;
mMaxSwapInterval = maxInterval;
mMinSwapInterval = minInterval;
mNativeRenderable = EGL_FALSE;
mNativeVisualID = 0;
mNativeVisualType = 0;
mRenderableType = EGL_OPENGL_ES2_BIT;
mSampleBuffers = multiSample ? 1 : 0;
mSamples = multiSample;
@@ -277,19 +277,19 @@ const EGLint ConfigSet::mSortAttribs[] =
EGL_NONE
};
ConfigSet::ConfigSet()
: mSet(SortConfig(mSortAttribs))
{
}
-void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
{
- Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
+ Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
mSet.insert(config);
}
size_t ConfigSet::size() const
{
return mSet.size();
}
@@ -332,16 +332,19 @@ bool ConfigSet::getConfigs(EGLConfig *co
case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == attribute[1]; break;
case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
+ case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
+ case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
+ case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
default:
return false;
}
if (!match)
{
break;
}
diff --git a/gfx/angle/src/libEGL/Config.h b/gfx/angle/src/libEGL/Config.h
--- a/gfx/angle/src/libEGL/Config.h
+++ b/gfx/angle/src/libEGL/Config.h
@@ -21,20 +21,20 @@
namespace egl
{
class Display;
class Config
{
public:
- Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+ Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
void setDefaults();
- void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+ void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
EGLConfig getHandle() const;
const D3DDISPLAYMODE mDisplayMode;
const D3DFORMAT mRenderTargetFormat;
const D3DFORMAT mDepthStencilFormat;
const EGLint mMultiSample;
EGLint mBufferSize; // Depth of the color buffer
@@ -94,17 +94,17 @@ class SortConfig
class ConfigSet
{
friend Display;
public:
ConfigSet();
- void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+ void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
size_t size() const;
bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
const egl::Config *get(EGLConfig configHandle);
private:
DISALLOW_COPY_AND_ASSIGN(ConfigSet);
typedef std::set<Config, SortConfig> Set;
diff --git a/gfx/angle/src/libEGL/Display.cpp b/gfx/angle/src/libEGL/Display.cpp
--- a/gfx/angle/src/libEGL/Display.cpp
+++ b/gfx/angle/src/libEGL/Display.cpp
@@ -175,17 +175,18 @@ bool Display::initialize()
if (SUCCEEDED(result))
{
HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
if (SUCCEEDED(result))
{
// FIXME: enumerate multi-sampling
- configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0);
+ configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
+ mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight);
}
}
}
}
}
// Give the sorted configs a unique ID and store them internally
EGLint index = 1;
@@ -317,16 +318,19 @@ bool Display::getConfigAttrib(EGLConfig
case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break;
case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break;
case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break;
case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break;
case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break;
case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break;
case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
case EGL_CONFORMANT: *value = configuration->mConformant; break;
+ case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break;
+ case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break;
+ case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break;
default:
return false;
}
return true;
}
bool Display::createDevice()
@@ -388,16 +392,26 @@ Surface *Display::createWindowSurface(HW
const Config *configuration = mConfigSet.get(config);
Surface *surface = new Surface(this, configuration, window);
mSurfaceSet.insert(surface);
return surface;
}
+Surface *Display::createOffscreenSurface(int width, int height, EGLConfig config)
+{
+ const Config *configuration = mConfigSet.get(config);
+
+ Surface *surface = new Surface(this, configuration, width, height);
+ mSurfaceSet.insert(surface);
+
+ return surface;
+}
+
EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
{
if (!mDevice)
{
if (!createDevice())
{
return NULL;
}
@@ -641,9 +655,9 @@ D3DPRESENT_PARAMETERS Display::getDefaul
presentParameters.MultiSampleQuality = 0;
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
return presentParameters;
}
-}
\ No newline at end of file
+}
diff --git a/gfx/angle/src/libEGL/Display.h b/gfx/angle/src/libEGL/Display.h
--- a/gfx/angle/src/libEGL/Display.h
+++ b/gfx/angle/src/libEGL/Display.h
@@ -38,16 +38,17 @@ class Display
virtual void startScene();
virtual void endScene();
bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
egl::Surface *createWindowSurface(HWND window, EGLConfig config);
+ egl::Surface *createOffscreenSurface(int width, int height, EGLConfig config);
EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);
void destroySurface(egl::Surface *surface);
void destroyContext(gl::Context *context);
bool isInitialized();
bool isValidConfig(EGLConfig config);
bool isValidContext(gl::Context *context);
@@ -63,16 +64,18 @@ class Display
virtual bool getCompressedTextureSupport();
virtual bool getEventQuerySupport();
virtual bool getFloatTextureSupport(bool *filtering, bool *renderable);
virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable);
virtual bool getLuminanceTextureSupport();
virtual bool getLuminanceAlphaTextureSupport();
virtual D3DPOOL getBufferPool(DWORD usage) const;
+ bool isD3d9exDevice() { return mD3d9ex != NULL; }
+
private:
DISALLOW_COPY_AND_ASSIGN(Display);
D3DPRESENT_PARAMETERS getDefaultPresentParameters();
const HDC mDc;
HMODULE mD3d9Module;
diff --git a/gfx/angle/src/libEGL/Surface.cpp b/gfx/angle/src/libEGL/Surface.cpp
--- a/gfx/angle/src/libEGL/Surface.cpp
+++ b/gfx/angle/src/libEGL/Surface.cpp
@@ -20,27 +20,48 @@
namespace egl
{
Surface::Surface(Display *display, const Config *config, HWND window)
: mDisplay(display), mConfig(config), mWindow(window)
{
mSwapChain = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
+ mOffscreenTexture = NULL;
+ mShareHandle = NULL;
mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
mRenderBuffer = EGL_BACK_BUFFER;
mSwapBehavior = EGL_BUFFER_PRESERVED;
mSwapInterval = -1;
setSwapInterval(1);
subclassWindow();
resetSwapChain();
}
+Surface::Surface(Display *display, const Config *config, EGLint width, EGLint height)
+ : mDisplay(display), mWindow(NULL), mConfig(config), mWidth(width), mHeight(height)
+{
+ mSwapChain = NULL;
+ mDepthStencil = NULL;
+ mRenderTarget = NULL;
+ mOffscreenTexture = NULL;
+ mShareHandle = NULL;
+ mWindowSubclassed = false;
+
+ mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
+ mRenderBuffer = EGL_BACK_BUFFER;
+ mSwapBehavior = EGL_BUFFER_PRESERVED;
+ mSwapInterval = -1;
+ setSwapInterval(1);
+
+ resetSwapChain(width, height);
+}
+
Surface::~Surface()
{
unsubclassWindow();
release();
}
void Surface::release()
{
@@ -56,20 +77,31 @@ void Surface::release()
mDepthStencil = NULL;
}
if (mRenderTarget)
{
mRenderTarget->Release();
mRenderTarget = NULL;
}
+
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->Release();
+ mOffscreenTexture = NULL;
+ }
}
void Surface::resetSwapChain()
{
+ if (!mWindow) {
+ resetSwapChain(mWidth, mHeight);
+ return;
+ }
+
RECT windowRect;
if (!GetClientRect(getWindowHandle(), &windowRect))
{
ASSERT(false);
ERR("Could not retrieve the window dimensions");
return;
}
@@ -85,40 +117,52 @@ void Surface::resetSwapChain(int backbuf
{
return;
}
// 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.
device->EvictManagedResources();
release();
-
+
D3DPRESENT_PARAMETERS presentParameters = {0};
+ HRESULT result;
presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
presentParameters.BackBufferCount = 1;
presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
presentParameters.EnableAutoDepthStencil = FALSE;
presentParameters.Flags = 0;
presentParameters.hDeviceWindow = getWindowHandle();
presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
presentParameters.PresentationInterval = mPresentInterval;
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
presentParameters.BackBufferWidth = backbufferWidth;
presentParameters.BackBufferHeight = backbufferHeight;
- HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+ if (mWindow)
+ {
+ result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+ } else {
+ HANDLE *pShareHandle = NULL;
+ if (mDisplay->isD3d9exDevice()) {
+ pShareHandle = &mShareHandle;
+ }
+
+ result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
+ presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
+ }
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- ERR("Could not create additional swap chains: %08lX", result);
+ ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
release();
return error(EGL_BAD_ALLOC);
}
result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL);
@@ -126,23 +170,27 @@ void Surface::resetSwapChain(int backbuf
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
release();
return error(EGL_BAD_ALLOC);
}
- mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget);
+ if (mWindow) {
+ mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget);
+ InvalidateRect(mWindow, NULL, FALSE);
+ } else {
+ mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
+ }
+
mWidth = presentParameters.BackBufferWidth;
mHeight = presentParameters.BackBufferHeight;
mPresentIntervalDirty = false;
-
- InvalidateRect(mWindow, NULL, FALSE);
}
HWND Surface::getWindowHandle()
{
return mWindow;
}
@@ -157,16 +205,19 @@ static LRESULT CALLBACK SurfaceWindowPro
}
}
WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
}
void Surface::subclassWindow()
{
+ if (!mWindow)
+ return;
+
SetLastError(0);
LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast<LONG>(SurfaceWindowProc));
if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) {
mWindowSubclassed = false;
return;
}
SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
diff --git a/gfx/angle/src/libEGL/Surface.h b/gfx/angle/src/libEGL/Surface.h
--- a/gfx/angle/src/libEGL/Surface.h
+++ b/gfx/angle/src/libEGL/Surface.h
@@ -21,41 +21,47 @@ namespace egl
{
class Display;
class Config;
class Surface
{
public:
Surface(Display *display, const egl::Config *config, HWND window);
+ Surface(Display *display, const egl::Config *config, EGLint width, EGLint height);
~Surface();
void release();
void resetSwapChain();
HWND getWindowHandle();
bool swap();
virtual EGLint getWidth() const;
virtual EGLint getHeight() const;
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
+ HANDLE getShareHandle() { return mShareHandle; }
+
void setSwapInterval(EGLint interval);
bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
private:
DISALLOW_COPY_AND_ASSIGN(Surface);
Display *const mDisplay;
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mDepthStencil;
IDirect3DSurface9* mRenderTarget;
+ IDirect3DTexture9* mOffscreenTexture;
+
+ HANDLE mShareHandle;
void subclassWindow();
void unsubclassWindow();
void resetSwapChain(int backbufferWidth, int backbufferHeight);
static DWORD convertInterval(EGLint interval);
const HWND mWindow; // Window that the surface is created for.
bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
diff --git a/gfx/angle/src/libEGL/libEGL.cpp b/gfx/angle/src/libEGL/libEGL.cpp
--- a/gfx/angle/src/libEGL/libEGL.cpp
+++ b/gfx/angle/src/libEGL/libEGL.cpp
@@ -189,17 +189,17 @@ const char *__stdcall eglQueryString(EGL
return NULL;
}
switch (name)
{
case EGL_CLIENT_APIS:
return success("OpenGL_ES");
case EGL_EXTENSIONS:
- return success("");
+ return success("EGL_ANGLE_query_surface_pointer EGL_ANGLE_surface_d3d_share_handle");
case EGL_VENDOR:
return success("Google Inc.");
case EGL_VERSION:
return success("1.4 (ANGLE "VERSION_STRING")");
}
return error(EGL_BAD_PARAMETER, (const char*)NULL);
}
@@ -386,25 +386,71 @@ EGLSurface __stdcall eglCreateWindowSurf
EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
dpy, config, attrib_list);
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
+ EGLint width = 0, height = 0;
if (!validate(display, config))
{
return EGL_NO_SURFACE;
}
- UNIMPLEMENTED(); // FIXME
+ if (attrib_list)
+ {
+ while (*attrib_list != EGL_NONE)
+ {
+ switch (attrib_list[0])
+ {
+ case EGL_WIDTH:
+ width = attrib_list[1];
+ break;
+ case EGL_HEIGHT:
+ height = attrib_list[1];
+ break;
+ case EGL_LARGEST_PBUFFER:
+ if (attrib_list[1] != EGL_FALSE)
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_TEXTURE_FORMAT:
+ case EGL_TEXTURE_TARGET:
+ switch (attrib_list[1])
+ {
+ case EGL_NO_TEXTURE:
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ if (attrib_list[1] != EGL_FALSE)
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ break;
+ case EGL_VG_COLORSPACE:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ case EGL_VG_ALPHA_FORMAT:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
- return success(EGL_NO_DISPLAY);
+ attrib_list += 2;
+ }
+ }
+
+ if (width == 0 || height == 0)
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+
+ EGLSurface surface = (EGLSurface)display->createOffscreenSurface(width, height, config);
+
+ return success(surface);
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
return EGL_NO_SURFACE;
}
@@ -420,17 +466,17 @@ EGLSurface __stdcall eglCreatePixmapSurf
if (!validate(display, config))
{
return EGL_NO_SURFACE;
}
UNIMPLEMENTED(); // FIXME
- return success(EGL_NO_DISPLAY);
+ return success(EGL_NO_SURFACE);
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
return EGL_NO_SURFACE;
}
@@ -545,16 +591,56 @@ EGLBoolean __stdcall eglQuerySurface(EGL
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_FALSE);
}
return EGL_FALSE;
}
+EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
+ dpy, surface, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ egl::Surface *eglSurface = (egl::Surface*)surface;
+
+ switch (attribute)
+ {
+ case EGL_D3D_TEXTURE_SHARE_HANDLE_ANGLE:
+ *value = (void*) eglSurface->getShareHandle();
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
EGLBoolean __stdcall eglBindAPI(EGLenum api)
{
EVENT("(EGLenum api = 0x%X)", api);
try
{
switch (api)
{
@@ -694,19 +780,19 @@ EGLBoolean __stdcall eglBindTexImage(EGL
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display))
{
return EGL_FALSE;
}
- UNIMPLEMENTED(); // FIXME
+ // FIXME - need implementation
- return success(EGL_TRUE);
+ return success(EGL_FALSE);
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_FALSE);
}
return EGL_FALSE;
}
@@ -719,19 +805,19 @@ EGLBoolean __stdcall eglReleaseTexImage(
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display))
{
return EGL_FALSE;
}
- UNIMPLEMENTED(); // FIXME
+ // FIXME - need implementation
- return success(EGL_TRUE);
+ return success(EGL_FALSE);
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_FALSE);
}
return EGL_FALSE;
}
@@ -1088,16 +1174,17 @@ __eglMustCastToProperFunctionPointerType
struct Extension
{
const char *name;
__eglMustCastToProperFunctionPointerType address;
};
static const Extension eglExtensions[] =
{
+ {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
{"", NULL},
};
for (int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
{
if (strcmp(procname, eglExtensions[ext].name) == 0)
{
return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
diff --git a/gfx/angle/src/libEGL/main.h b/gfx/angle/src/libEGL/main.h
--- a/gfx/angle/src/libEGL/main.h
+++ b/gfx/angle/src/libEGL/main.h
@@ -6,16 +6,17 @@
// main.h: Management of thread-local data.
#ifndef LIBEGL_MAIN_H_
#define LIBEGL_MAIN_H_
#define EGLAPI
#include <EGL/egl.h>
+#include <EGL/eglext.h>
namespace egl
{
struct Current
{
EGLint error;
EGLenum API;
EGLDisplay display;
diff --git a/gfx/layers/d3d10/CanvasLayerD3D10.cpp b/gfx/layers/d3d10/CanvasLayerD3D10.cpp
--- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp
+++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp
@@ -83,18 +83,22 @@ CanvasLayerD3D10::Initialize(const Data&
}
mIsD2DTexture = PR_FALSE;
mUsingSharedTexture = PR_FALSE;
HANDLE shareHandle = mGLContext ? mGLContext->GetD3DShareHandle() : nsnull;
if (shareHandle) {
HRESULT hr = device()->OpenSharedResource(shareHandle, __uuidof(ID3D10Texture2D), getter_AddRefs(mTexture));
- if (SUCCEEDED(hr))
+ if (SUCCEEDED(hr)) {
mUsingSharedTexture = PR_TRUE;
+ // XXX for ANGLE, it's already the right-way up. If we start using NV GL-D3D interop
+ // however, we'll need to do the right thing.
+ mNeedsYFlip = PR_FALSE;
+ }
}
if (!mUsingSharedTexture) {
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
desc.Usage = D3D10_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTexture));
diff --git a/gfx/thebes/GLContextProviderEGL.cpp b/gfx/thebes/GLContextProviderEGL.cpp
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -391,18 +391,18 @@ public:
NS_WARNING("Couldn't find required entry points in EGL library (early init)");
return PR_FALSE;
}
mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY);
if (!fInitialize(mEGLDisplay, NULL, NULL))
return PR_FALSE;
- const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
- if (vendor && strstr(vendor, "TransGaming") != 0) {
+ const char *version = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VERSION);
+ if (version && strstr(version, "ANGLE") != 0) {
mIsANGLE = PR_TRUE;
}
const char *extensions = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
if (!extensions)
extensions = "";
printf_stderr("Extensions: %s 0x%02x\n", extensions, extensions[0]);

Просмотреть файл

@ -0,0 +1,222 @@
# HG changeset patch
# Parent 593e84b864c5470aa43682d308212878b0b4e5d9
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -72,17 +72,17 @@ CPPSRCS = \
parseConst.cpp \
ParseHelper.cpp \
PoolAlloc.cpp \
QualifierAlive.cpp \
RemoveTree.cpp \
ShaderLang.cpp \
SymbolTable.cpp \
VariableInfo.cpp \
- debug.cpp \
+ compilerdebug.cpp \
ossource_nspr.cpp \
util.cpp \
ValidateLimitations.cpp \
$(NULL)
# flex/yacc generated files
CPPSRCS += \
glslang_lex.cpp \
diff --git a/gfx/angle/src/build_angle.gyp b/gfx/angle/src/build_angle.gyp
--- a/gfx/angle/src/build_angle.gyp
+++ b/gfx/angle/src/build_angle.gyp
@@ -17,18 +17,18 @@
'.',
'../include',
],
'sources': [
'compiler/BaseTypes.h',
'compiler/Common.h',
'compiler/Compiler.cpp',
'compiler/ConstantUnion.h',
- 'compiler/debug.cpp',
- 'compiler/debug.h',
+ 'compiler/compilerdebug.cpp',
+ 'compiler/compilerdebug.h',
'compiler/glslang.h',
'compiler/glslang_lex.cpp',
'compiler/glslang_tab.cpp',
'compiler/glslang_tab.h',
'compiler/InfoSink.cpp',
'compiler/InfoSink.h',
'compiler/Initialize.cpp',
'compiler/Initialize.h',
diff --git a/gfx/angle/src/compiler/OutputGLSL.cpp b/gfx/angle/src/compiler/OutputGLSL.cpp
--- a/gfx/angle/src/compiler/OutputGLSL.cpp
+++ b/gfx/angle/src/compiler/OutputGLSL.cpp
@@ -1,16 +1,16 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/OutputGLSL.h"
-#include "compiler/debug.h"
+#include "compiler/compilerdebug.h"
namespace
{
TString getTypeName(const TType& type)
{
TInfoSinkBase out;
if (type.isMatrix())
{
diff --git a/gfx/angle/src/compiler/OutputHLSL.cpp b/gfx/angle/src/compiler/OutputHLSL.cpp
--- a/gfx/angle/src/compiler/OutputHLSL.cpp
+++ b/gfx/angle/src/compiler/OutputHLSL.cpp
@@ -1,17 +1,17 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/OutputHLSL.h"
-#include "compiler/debug.h"
+#include "compiler/compilerdebug.h"
#include "compiler/InfoSink.h"
#include "compiler/UnfoldSelect.h"
#include "compiler/SearchSymbol.h"
#include <stdio.h>
#include <algorithm>
namespace sh
diff --git a/gfx/angle/src/compiler/Types.h b/gfx/angle/src/compiler/Types.h
--- a/gfx/angle/src/compiler/Types.h
+++ b/gfx/angle/src/compiler/Types.h
@@ -4,17 +4,17 @@
// found in the LICENSE file.
//
#ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED
#include "compiler/BaseTypes.h"
#include "compiler/Common.h"
-#include "compiler/debug.h"
+#include "compiler/compilerdebug.h"
//
// Need to have association of line numbers to types in a list for building structs.
//
class TType;
struct TTypeLine {
TType* type;
int line;
diff --git a/gfx/angle/src/compiler/compilerdebug.cpp b/gfx/angle/src/compiler/compilerdebug.cpp
--- a/gfx/angle/src/compiler/compilerdebug.cpp
+++ b/gfx/angle/src/compiler/compilerdebug.cpp
@@ -1,17 +1,17 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// debug.cpp: Debugging utilities.
+// compilerdebug.cpp: Debugging utilities.
-#include "compiler/debug.h"
+#include "compiler/compilerdebug.h"
#include <stdarg.h>
#include <stdio.h>
#include "compiler/ParseHelper.h"
static const int kTraceBufferLen = 1024;
diff --git a/gfx/angle/src/compiler/compilerdebug.h b/gfx/angle/src/compiler/compilerdebug.h
--- a/gfx/angle/src/compiler/compilerdebug.h
+++ b/gfx/angle/src/compiler/compilerdebug.h
@@ -1,15 +1,15 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// debug.h: Debugging utilities.
+// compilerdebug.h: Debugging utilities.
#ifndef COMPILER_DEBUG_H_
#define COMPILER_DEBUG_H_
#include <assert.h>
#ifdef _DEBUG
#define TRACE_ENABLED // define to enable debug message tracing
diff --git a/gfx/angle/src/compiler/osinclude.h b/gfx/angle/src/compiler/osinclude.h
--- a/gfx/angle/src/compiler/osinclude.h
+++ b/gfx/angle/src/compiler/osinclude.h
@@ -32,17 +32,17 @@
#include <windows.h>
#elif defined(ANGLE_OS_POSIX)
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#endif // ANGLE_USE_NSPR
-#include "compiler/debug.h"
+#include "compiler/compilerdebug.h"
//
// Thread Local Storage Operations
//
#if defined(ANGLE_USE_NSPR)
typedef PRUintn OS_TLSIndex;
#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
#elif defined(ANGLE_OS_WIN)
diff --git a/gfx/angle/src/compiler/preprocessor/atom.c b/gfx/angle/src/compiler/preprocessor/atom.c
--- a/gfx/angle/src/compiler/preprocessor/atom.c
+++ b/gfx/angle/src/compiler/preprocessor/atom.c
@@ -45,17 +45,17 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILI
//
// atom.c
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include "compiler/debug.h"
+#include "compiler/compilerdebug.h"
#include "compiler/preprocessor/slglobals.h"
#undef malloc
#undef realloc
#undef free
///////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////// String table: //////////////////////////////////////
diff --git a/gfx/angle/src/compiler/preprocessor/tokens.c b/gfx/angle/src/compiler/preprocessor/tokens.c
--- a/gfx/angle/src/compiler/preprocessor/tokens.c
+++ b/gfx/angle/src/compiler/preprocessor/tokens.c
@@ -45,17 +45,17 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILI
// tokens.c
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
-#include "compiler/debug.h"
+#include "compiler/compilerdebug.h"
#include "compiler/preprocessor/slglobals.h"
#include "compiler/util.h"
///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////// Preprocessor and Token Recorder and Playback: ////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
/*

Просмотреть файл

@ -0,0 +1,427 @@
Name
ANGLE_framebuffer_blit
Name Strings
GL_ANGLE_framebuffer_blit
Contributors
Contributors to EXT_framebuffer_blit
Daniel Koch, TransGaming Inc.
Shannon Woods, TransGaming Inc.
Kenneth Russell, Google Inc.
Vangelis Kokkevis, Google Inc.
Contact
Daniel Koch, TransGaming Inc. (daniel 'at' transgaming 'dot' com)
Status
Implemented in ANGLE ES2
Version
Last Modified Date: Aug 6, 2010
Author Revision: 3
Number
OpenGL ES Extension #83
Dependencies
OpenGL ES 2.0 is required.
The extension is written against the OpenGL ES 2.0 specification.
OES_texture_3D affects the definition of this extension.
Overview
This extension modifies framebuffer objects by splitting the
framebuffer object binding point into separate DRAW and READ
bindings. This allows copying directly from one framebuffer to
another. In addition, a new high performance blit function is
added to facilitate these blits and perform some data conversion
where allowed.
IP Status
No known IP claims.
New Procedures and Functions
void BlitFramebufferANGLE(int srcX0, int srcY0, int srcX1, int srcY1,
int dstX0, int dstY0, int dstX1, int dstY1,
bitfield mask, enum filter);
New Tokens
Accepted by the <target> parameter of BindFramebuffer,
CheckFramebufferStatus, FramebufferTexture2D, FramebufferTexture3DOES,
FramebufferRenderbuffer, and
GetFramebufferAttachmentParameteriv:
// (reusing the tokens from EXT_framebuffer_blit)
READ_FRAMEBUFFER_ANGLE 0x8CA8
DRAW_FRAMEBUFFER_ANGLE 0x8CA9
Accepted by the <pname> parameters of GetIntegerv and GetFloatv:
// (reusing the tokens from EXT_framebuffer_blit)
DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 // alias FRAMEBUFFER_BINDING
READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
Change the last paragraph of section 3.7.2 (Alternate Texture Image
Specification Commands) to:
"Calling CopyTexSubImage3DOES, CopyTexImage2D or CopyTexSubImage2D will
result in an INVALID_FRAMEBUFFER_OPERATION error if the object bound
to READ_FRAMEBUFFER_BINDING_ANGLE is not "framebuffer complete"
(section 4.4.4.2)."
Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
Operations and the Framebuffer)
Change the first word of Chapter 4 from "The" to "A".
Append to the introduction of Chapter 4:
"Conceptually, the GL has two active framebuffers; the draw
framebuffer is the destination for rendering operations, and the
read framebuffer is the source for readback operations. The same
framebuffer may be used for both drawing and reading. Section
4.4.1 describes the mechanism for controlling framebuffer usage."
Modify the first sentence of the last paragraph of section 4.1.1 as follows:
"While an application-created framebuffer object is bound to
DRAW_FRAMEBUFFER_ANGLE, the pixel ownership test always passes."
Add to 4.3.1 (Reading Pixels), right before the subsection titled
"Obtaining Pixels from the Framebuffer":
"Calling ReadPixels generates INVALID_FRAMEBUFFER_OPERATION if
the object bound to READ_FRAMEBUFFER_BINDING_ANGLE is not "framebuffer
complete" (section 4.4.4.2)."
Insert a new section 4.3.2 titled "Copying Pixels" and renumber the
subsequent sections. Add the following text:
"BlitFramebufferANGLE transfers a rectangle of pixel values from one
region of the read framebuffer to another in the draw framebuffer.
BlitFramebufferANGLE(int srcX0, int srcY0, int srcX1, int srcY1,
int dstX0, int dstY0, int dstX1, int dstY1,
bitfield mask, enum filter);
<mask> is the bitwise OR of a number of values indicating which
buffers are to be copied. The values are COLOR_BUFFER_BIT,
DEPTH_BUFFER_BIT, and STENCIL_BUFFER_BIT, which are described in
section 4.2.3. The pixels corresponding to these buffers are
copied from the source rectangle, bound by the locations (srcX0,
srcY0) and (srcX1, srcY1), to the destination rectangle, bound by
the locations (dstX0, dstY0) and (dstX1, dstY1). The lower bounds
of the rectangle are inclusive, while the upper bounds are
exclusive.
The actual region taken from the read framebuffer is limited to the
intersection of the source buffers being transferred, which may include
the color buffer, the depth buffer, and/or the stencil buffer depending on
<mask>. The actual region written to the draw framebuffer is limited to the
intersection of the destination buffers being written, which may include
the color buffer, the depth buffer, and/or the stencil buffer
depending on <mask>. Whether or not the source or destination regions are
altered due to these limits, the offset applied to pixels being transferred
is performed as though no such limits were present.
Stretching and scaling during a copy are not supported. If the source
and destination rectangle dimensions do not match, no copy is
performed and an INVALID_OPERATION error is generated.
Because stretching is not supported, <filter> must be NEAREST and
no filtering is applied.
Flipping during a copy is not supported. If either the source or
destination rectangle specifies a negative dimension, the error
INVALID_OPERATION is generated. If both the source and
destination rectangles specify a negative dimension for the same
direction, no reversal is required and the operation is supported.
If the source and destination buffers are identical, and the
source and destination rectangles overlap, the result of the blit
operation is undefined.
The pixel copy bypasses the fragment pipeline. The only fragment
operations which affect the blit are the pixel ownership test and
the scissor test.
If a buffer is specified in <mask> and does not exist in both the
read and draw framebuffers, the corresponding bit is silently
ignored.
Calling BlitFramebufferANGLE will result in an
INVALID_FRAMEBUFFER_OPERATION error if the objects bound to
DRAW_FRAMEBUFFER_BINDING_ANGLE and READ_FRAMEBUFFER_BINDING_ANGLE are
not "framebuffer complete" (section 4.4.4.2)."
Calling BlitFramebufferANGLE will result in an INVALID_OPERATION
error if <mask> includes COLOR_BUFFER_BIT and the source and
destination color formats to not match.
Calling BlitFramebufferANGLE will result in an INVALID_OPERATION
error if <mask> includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT
and the source and destination depth and stencil buffer formats do
not match.
If <mask> includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT, only
complete buffers can be copied. If the source rectangle does not
specify the complete source buffer or the destination rectangle
(after factoring the scissor region, if applicable) does not specify
the complete destination buffer, an INVALID_OPERATION
error is generated.
Modify the beginning of section 4.4.1 as follows:
"The default framebuffer for rendering and readback operations is
provided by the windowing system. In addition, named framebuffer
objects can be created and operated upon. The namespace for
framebuffer objects is the unsigned integers, with zero reserved
by the GL for the default framebuffer.
A framebuffer object is created by binding an unused name to
DRAW_FRAMEBUFFER_ANGLE or READ_FRAMEBUFFER_ANGLE. The binding is
effected by calling
void BindFramebuffer(enum target, uint framebuffer);
with <target> set to the desired framebuffer target and
<framebuffer> set to the unused name. The resulting framebuffer
object is a new state vector, comprising one set of the state values
listed in table 6.23 for each attachment point of the
framebuffer, set to the same initial values. There is one
color attachment point, plus one each
for the depth and stencil attachment points.
BindFramebuffer may also be used to bind an existing
framebuffer object to DRAW_FRAMEBUFFER_ANGLE or
READ_FRAMEBUFFER_ANGLE. If the bind is successful no change is made
to the state of the bound framebuffer object, and any previous
binding to <target> is broken.
If a framebuffer object is bound to DRAW_FRAMEBUFFER_ANGLE or
READ_FRAMEBUFFER_ANGLE, it becomes the target for rendering or
readback operations, respectively, until it is deleted or another
framebuffer is bound to the corresponding bind point. Calling
BindFramebuffer with <target> set to FRAMEBUFFER binds the
framebuffer to both DRAW_FRAMEBUFFER_ANGLE and READ_FRAMEBUFFER_ANGLE.
While a framebuffer object is bound, GL operations on the target
to which it is bound affect the images attached to the bound
framebuffer object, and queries of the target to which it is bound
return state from the bound object. Queries of the values
specified in table 6.20 (Implementation Dependent Pixel Depths)
and table 6.yy (Framebuffer Dependent Values) are
derived from the framebuffer object bound to DRAW_FRAMEBUFFER_ANGLE.
The initial state of DRAW_FRAMEBUFFER_ANGLE and READ_FRAMEBUFFER_ANGLE
refers to the default framebuffer provided by the windowing
system. In order that access to the default framebuffer is not
lost, it is treated as a framebuffer object with the name of 0.
The default framebuffer is therefore rendered to and read from
while 0 is bound to the corresponding targets. On some
implementations, the properties of the default framebuffer can
change over time (e.g., in response to windowing system events
such as attaching the context to a new windowing system drawable.)"
Change the description of DeleteFramebuffers as follows:
"<framebuffers> contains <n> names of framebuffer objects to be
deleted. After a framebuffer object is deleted, it has no
attachments, and its name is again unused. If a framebuffer that
is currently bound to one or more of the targets
DRAW_FRAMEBUFFER_ANGLE or READ_FRAMEBUFFER_ANGLE is deleted, it is as
though BindFramebuffer had been executed with the corresponding
<target> and <framebuffer> zero. Unused names in <framebuffers>
are silently ignored, as is the value zero."
In section 4.4.3 (Renderbuffer Objects), modify the first two sentences
of the description of FramebufferRenderbuffer as follows:
"<target> must be DRAW_FRAMEBUFFER_ANGLE, READ_FRAMEBUFFER_ANGLE, or
FRAMEBUFFER. If <target> is FRAMEBUFFER, it behaves as
though DRAW_FRAMEBUFFER_ANGLE was specified. The INVALID_OPERATION
error is generated if the value of the corresponding binding is zero."
In section 4.4.3 (Renderbuffer Objects), modify the first two sentences
of the description of FramebufferTexture2D as follows:
"<target> must be DRAW_FRAMEBUFFER_ANGLE,
READ_FRAMEBUFFER_ANGLE, or FRAMEBUFFER. If <target> is
FRAMEBUFFER, it behaves as though DRAW_FRAMEBUFFER_ANGLE was
specified. The INVALID_OPERATION error is generated if the value of the
corresponding binding is zero."
In section 4.4.5 (Framebuffer Completeness), modify the first sentence
of the description of CheckFramebufferStatus as follows:
"If <target> is not DRAW_FRAMEBUFFER_ANGLE, READ_FRAMEBUFFER_ANGLE or
FRAMEBUFFER, the error INVALID_ENUM is generated. If <target> is
FRAMEBUFFER, it behaves as though DRAW_FRAMEBUFFER_ANGLE was
specified."
Modify the first sentence of the subsection titled "Effects of Framebuffer
Completeness on Framebuffer Operations" to be:
"Attempting to render to or read from a framebuffer which is not
framebuffer complete will generate an
INVALID_FRAMEBUFFER_OPERATION error."
Additions to Chapter 6 of the OpenGL 1.5 Specification (State and State
Requests)
In section 6.1.3, modify the first sentence of the description of
GetFramebufferAttachmentParameteriv as follows:
"<target> must be DRAW_FRAMEBUFFER_ANGLE, READ_FRAMEBUFFER_ANGLE or
FRAMEBUFFER. If <target> is FRAMEBUFFER, it behaves as
though DRAW_FRAMEBUFFER_ANGLE was specified."
Modify the title of Table 6.23 (Framebuffer State) to be "Framebuffer
(state per attachment point)".
Dependencies on OES_texture_3D
On an OpenGL ES implementation, in the absense of OES_texture_3D,
omit references to FramebufferTexture3DOES and CopyTexSubImage3DOES.
Errors
The error INVALID_FRAMEBUFFER_OPERATION is generated if
BlitFramebufferANGLE is called while the
draw framebuffer is not framebuffer complete.
The error INVALID_FRAMEBUFFER_OPERATION is generated if
BlitFramebufferANGLE, ReadPixels, CopyTex{Sub}Image*, is called while the
read framebuffer is not framebuffer complete.
The error INVALID_VALUE is generated by BlitFramebufferANGLE if
<mask> has any bits set other than those named by
COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT.
The error INVALID_OPERATION is generated if BlitFramebufferANGLE is
called and <mask> includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT
and the source and destination depth or stencil buffer formats do
not match.
The error INVALID_OPERATION is generated if BlitFramebufferANGLE is
called and any of the following conditions are true:
- the source and destination rectangle dimensions do not match
(ie scaling or flipping is required).
- <mask> includes COLOR_BUFFER_BIT and the source and destination
buffer formats do not match.
- <mask> includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT and the
source or destination rectangles do not specify the entire source
or destination buffer (after applying any scissor region).
The error INVALID_ENUM is generated by BlitFramebufferANGLE if
<filter> is not NEAREST.
The error INVALID_ENUM is generated if BindFramebuffer,
CheckFramebufferStatus, FramebufferTexture{2D|3DOES},
FramebufferRenderbuffer, or
GetFramebufferAttachmentParameteriv is called and <target> is
not DRAW_FRAMEBUFFER_ANGLE, READ_FRAMEBUFFER_ANGLE or FRAMEBUFFER.
New State
(Add a new table 6.xx, "Framebuffer (state per framebuffer target binding point)")
Get Value Type Get Command Initial Value Description Section
------------------------------ ---- ----------- -------------- ------------------- ------------
DRAW_FRAMEBUFFER_BINDING_ANGLE Z+ GetIntegerv 0 framebuffer object bound 4.4.1
to DRAW_FRAMEBUFFER_ANGLE
READ_FRAMEBUFFER_BINDING_ANGLE Z+ GetIntegerv 0 framebuffer object 4.4.1
to READ_FRAMEBUFFER_ANGLE
Remove reference to FRAMEBUFFER_BINDING from Table 6.23.
(Add a new table 6.yy, "Framebuffer Dependent Values")
Get Value Type Get Command Initial Value Description Section
---------------------------- ---- ----------- -------------- ------------------- ------------
SAMPLE_BUFFERS Z+ GetIntegerv 0 Number of multisample 3.2
buffers
SAMPLES Z+ GetIntegerv 0 Coverage mask size 3.2
Remove the references to SAMPLE_BUFFERS and SAMPLES from Table 6.17.
Issues
1) What should we call this extension?
Resolved: ANGLE_framebuffer_blit.
This extension is a result of a collaboration between Google and
TransGaming for the open-source ANGLE project. Typically one would
label a multi-vendor extension as EXT, but EXT_framebuffer_blit
is already the name for this on Desktop GL. Additionally this
isn't truely a multi-vendor extension because there is only one
implementation of this. We'll follow the example of the open-source
MESA project which uses the project name for the vendor suffix.
2) Why is this done as a separate extension instead of just supporting
EXT_framebuffer_blit?
To date, EXT_framebuffer_blit has not had interactions with OpenGL ES
specified and, as far as we know, it has not previously been exposed on
an ES 1.1 or ES 2.0 implementation. Because there are enough
differences between Desktop GL and OpenGL ES, and since OpenGL ES 2.0
has already subsumed the EXT_framebuffer_object functionality (with
some changes) it was deemed a worthwhile exercise to fully specify the
interactions. Additionally, some of the choices in exactly which
functionality is supported by BlitFramebufferANGLE is dictated by
what is reasonable to support on a implementation which is
layered on Direct3D9. It is not expected that other implementations
will necessary have the same set of restrictions or requirements.
3) How does this extension differ from EXT_framebuffer_blit?
This extension is designed to be a pure subset of the
EXT_framebuffer_blit functionality as applicable to OpenGL ES 2.0.
Functionality that is unchanged:
- the split DRAW and READ framebuffer attachment points and related sematics.
- the token values for the DRAW/READ_FRAMEBUFFER and DRAW/READ_FRAMBUFFER_BINDING
- the signature of the BlitFramebuffer entry-point.
Additional restrictions imposed by BlitFramebufferANGLE:
- no color conversions are supported
- no scaling, stretching or flipping are supported
- no filtering is supported (a consequence of no stretching)
- only whole depth and/or stencil buffers can be copied
Revision History
Revision 1, 2010/07/06
- copied from revision 15 of EXT_framebuffer_object
- removed language that was clearly not relevant to ES2
- rebased changes against the OpenGL ES 2.0 specification
- added ANGLE-specific restrictions
Revision 2, 2010/07/15
- clarifications of implicit clamping to buffer sizes (from ARB_fbo)
- clarify that D/S restricts apply after the scissor is applied
- improve some error language
Revision 3, 2010/08/06
- add additional contributors, update implementation status

Просмотреть файл

@ -0,0 +1,363 @@
Name
ANGLE_framebuffer_multisample
Name Strings
GL_ANGLE_framebuffer_multisample
Contributors
Contributors to EXT_framebuffer_multisample
Daniel Koch, TransGaming Inc.
Shannon Woods, TransGaming Inc.
Kenneth Russell, Google Inc.
Vangelis Kokkevis, Google Inc.
Contacts
Daniel Koch, TransGaming Inc. (daniel 'at' transgaming 'dot' com)
Status
Implemented in ANGLE ES2
Version
Last Modified Date: Aug 6, 2010
Author Revision: #3
Number
OpenGL ES Extension #84
Dependencies
Requires OpenGL ES 2.0.
Requires GL_ANGLE_framebuffer_blit (or equivalent functionality).
The extension is written against the OpenGL ES 2.0 specification.
OES_texture_3D affects the definition of this extension.
Overview
This extension extends the framebuffer object framework to
enable multisample rendering.
The new operation RenderbufferStorageMultisampleANGLE() allocates
storage for a renderbuffer object that can be used as a multisample
buffer. A multisample render buffer image differs from a
single-sample render buffer image in that a multisample image has a
number of SAMPLES that is greater than zero. No method is provided
for creating multisample texture images.
All of the framebuffer-attachable images attached to a framebuffer
object must have the same number of SAMPLES or else the framebuffer
object is not "framebuffer complete". If a framebuffer object with
multisample attachments is "framebuffer complete", then the
framebuffer object behaves as if SAMPLE_BUFFERS is one.
The resolve operation is affected by calling
BlitFramebufferANGLE (provided by the ANGLE_framebuffer_blit
extension) where the source is a multisample application-created
framebuffer object and the destination is a single-sample
framebuffer object (either application-created or window-system
provided).
New Procedures and Functions
void RenderbufferStorageMultisampleANGLE(
enum target, sizei samples,
enum internalformat,
sizei width, sizei height);
New Types
None.
New Tokens
Accepted by the <pname> parameter of GetRenderbufferParameteriv:
RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
Returned by CheckFramebufferStatus:
FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
and GetFloatv:
MAX_SAMPLES_ANGLE 0x8D57
Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL Operation)
Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
Add to the last paragraph of 3.7.2 (Alternate Texture Image Specification)
(as modified by ANGLE_framebuffer_blit) the following:
"Calling CopyTexSubImage3DOES, CopyTexImage2D or CopyTexSubImage2D will
result in INVALID_OPERATION being generated if the object bound to
READ_FRAMEBUFFER_BINDING_ANGLE is "framebuffer complete" and the value
of SAMPLE_BUFFERS is greater than zero."
Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
Operations and the Framebuffer)
Add to 4.3.1 (Reading Pixels), right before the subsection titled
"Obtaining Pixels from the Framebuffer":
"ReadPixels generates INVALID_OPERATION if READ_FRAMEBUFFER_BINDING_ANGLE
(section 4.4) is non-zero, the read framebuffer is framebuffer
complete, and the value of SAMPLE_BUFFERS for the read framebuffer
is greater than zero."
In 4.3.2 (Copying Pixels), add to the section describing BlitFramebuffer
that was added by ANGLE_framebuffer_blit.
"If SAMPLE_BUFFERS for the read framebuffer is greater than zero and
SAMPLE_BUFFERS for the draw framebuffer is zero, the samples
corresponding to each pixel location in the source are converted to
a single sample before being written to the destination.
If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
no copy is performed and an INVALID_OPERATION error is generated.
If SAMPLE_BUFFERS for the read framebuffer is greater than zero and
<mask> includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT, no copy is
performed and an INVALID_OPERATION error is generated.
If SAMPLE_BUFFERS for the read framebuffer is greater than zero and
the format of the read and draw framebuffers are not identical, no
copy is performed and an INVALID_OPERATION error is generated.
If SAMPLE_BUFFERS for the read framebuffer is greater than zero, the
dimensions of the source and destination rectangles provided to
BlitFramebufferANGLE must be identical and must specify the complete
source and destination buffers, otherwise no copy is performed and
an INVALID_OPERATION error is generated."
Modification to 4.4.3 (Renderbuffer Objects)
Add, just above the definition of RenderbufferStorage:
"The command
void RenderbufferStorageMultisampleANGLE(
enum target, sizei samples,
enum internalformat,
sizei width, sizei height);
establishes the data storage, format, dimensions, and number of
samples of a renderbuffer object's image. <target> must be
RENDERBUFFER. <internalformat> must be one of the color-renderable,
depth-renderable, or stencil-renderable formats described in table 4.5.
<width> and <height> are the dimensions in pixels of the renderbuffer. If
either <width> or <height> is greater than the value of
MAX_RENDERBUFFER_SIZE, or if <samples> is greater than MAX_SAMPLES_ANGLE,
then the error INVALID_VALUE is generated. If OpenGL ES is unable to
create a data store of the requested size, the error OUT_OF_MEMORY
is generated.
Upon success, RenderbufferStorageMultisampleANGLE deletes any existing
data store for the renderbuffer image and the contents of the data
store after calling RenderbufferStorageMultisampleANGLE are undefined.
RENDERBUFFER_WIDTH is set to <width>, RENDERBUFFER_HEIGHT is
set to <height>, and RENDERBUFFER_INTERNAL_FORMAT is set to
<internalformat>.
If <samples> is zero, then RENDERBUFFER_SAMPLES_ANGLE is set to zero.
Otherwise <samples> represents a request for a desired minimum
number of samples. Since different implementations may support
different sample counts for multisampled rendering, the actual
number of samples allocated for the renderbuffer image is
implementation dependent. However, the resulting value for
RENDERBUFFER_SAMPLES_ANGLE is guaranteed to be greater than or equal
to <samples> and no more than the next larger sample count supported
by the implementation.
An OpenGL ES implementation may vary its allocation of internal component
resolution based on any RenderbufferStorageMultisampleANGLE parameter (except
target), but the allocation and chosen internal format must not be a
function of any other state and cannot be changed once they are
established. The actual resolution in bits of each component of the
allocated image can be queried with GetRenderbufferParameteriv."
Modify the definiton of RenderbufferStorage as follows:
"The command
void RenderbufferStorage(enum target, enum internalformat,
sizei width, sizei height);
is equivalent to calling RenderbufferStorageMultisampleANGLE with
<samples> equal to zero."
In section 4.4.5 (Framebuffer Completeness) in the subsection
titled "Framebuffer Completeness" add an entry to the bullet list:
* The value of RENDERBUFFER_SAMPLES_ANGLE is the same for all attached
images.
{ FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE }
Also add a paragraph to the end of the section after the definition
of CheckFramebufferStatus:
"The values of SAMPLE_BUFFERS and SAMPLES are derived from the
attachments of the currently bound framebuffer object. If the
current DRAW_FRAMEBUFFER_BINDING_ANGLE is not "framebuffer complete",
then both SAMPLE_BUFFERS and SAMPLES are undefined. Otherwise,
SAMPLES is equal to the value of RENDERBUFFER_SAMPLES_ANGLE for the
attached images (which all must have the same value for
RENDERBUFFER_SAMPLES_ANGLE). Further, SAMPLE_BUFFERS is one if
SAMPLES is non-zero. Otherwise, SAMPLE_BUFFERS is zero.
Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
Requests)
In section 6.1.3 (Enumeraged Queries), modify the third paragraph
of the description of GetRenderbufferParameteriv as follows:
"Upon successful return from GetRenderbufferParameteriv, if
<pname> is RENDERBUFFER_WIDTH, RENDERBUFFER_HEIGHT,
RENDERBUFFER_INTERNAL_FORMAT, or RENDERBUFFER_SAMPLES_ANGLE, then <params>
will contain the width in pixels, height in pixels, internal format, or
number of samples, respectively, of the image of the renderbuffer
currently bound to <target>."
Dependencies on ANGLE_framebuffer_blit
ANGLE_framebuffer_blit is required. Technically, ANGLE_framebuffer_blit
would not be required to support multisampled rendering, except for
the fact that it provides the only method of doing a multisample
resovle from a multisample renderbuffer.
Dependencies on OES_texture_3D
On an OpenGL ES implementation, in the absense of OES_texture_3D,
omit references to CopyTexSubImage3DOES.
Errors
The error INVALID_OPERATION is generated if ReadPixels or
CopyTex{Sub}Image* is called while READ_FRAMEBUFFER_BINDING_ANGLE
is non-zero, the read framebuffer is framebuffer complete, and the
value of SAMPLE_BUFFERS for the read framebuffer is greater than
zero.
If both the draw and read framebuffers are framebuffer complete and
the draw framebuffer has a value of SAMPLE_BUFFERS that is greater
than zero, then the error INVALID_OPERATION is generated if
BlitFramebufferANGLE is called.
If both the draw and read framebuffers are framebuffer complete and
the read framebuffer has a value of SAMPLE_BUFFERS that is greater
than zero, the error INVALID_OPERATION is generated if
BlitFramebufferANGLE is called and any of the following conditions
are true:
- <mask> includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT.
- the source or destination rectangles do not specify the entire
source or destination buffer.
If both the draw and read framebuffers are framebuffer complete and
either has a value of SAMPLE_BUFFERS that is greater than zero, then
the error INVALID_OPERATION is generated if BlitFramebufferANGLE is
called and the formats of the draw and read framebuffers are not
identical.
If either the draw or read framebuffer is framebuffer complete and
has a value of SAMPLE_BUFFERS that is greater than zero, then the
error INVALID_OPERATION is generated if BlitFramebufferANGLE is called
and the specified source and destination dimensions are not
identical.
If RenderbufferStorageMultisampleANGLE is called with <target> not
equal to RENDERBUFFER, the error INVALID_ENUM is generated.
If RenderbufferStorageMultisampleANGLE is called with an
<internalformat> that is not listed as one of the color-, depth-
or stencil-renderable formats in Table 4.5, then the error
INVALID_ENUM is generated.
If RenderbufferStorageMultisampleANGLE is called with <width> or
<height> greater than MAX_RENDERBUFFER_SIZE, then the error
INVALID_VALUE is generated.
If RenderbufferStorageMultisampleANGLE is called with a value of
<samples> that is greater than MAX_SAMPLES_ANGLE or less than zero,
then the error INVALID_VALUE is generated.
The error OUT_OF_MEMORY is generated when
RenderbufferStorageMultisampleANGLE cannot create storage of the
specified size.
New State
Add to table 6.22 (Renderbuffer State)
Get Value Type Get Command Initial Value Description Section
------------------------------- ------ -------------------------- ------------- -------------------- -------
RENDERBUFFER_SAMPLES_ANGLE Z+ GetRenderbufferParameteriv 0 number of samples 4.4.3
Add to table 6.yy (Framebuffer Dependent Vaues) (added by
ANGLE_framebuffer_blit), the following new framebuffer dependent state.
Get Value Type Get Command Minimum Value Description Section
----------------- ---- ----------- ------------- ------------------- -------
MAX_SAMPLES_ANGLE Z+ GetIntegerv 1 Maximum number of 4.4.3
samples supported
for multisampling
Issues
Issues from EXT_framebuffer_multisample have been removed.
1) What should we call this extension?
Resolved: ANGLE_framebuffer_blit.
This extension is a result of a collaboration between Google and
TransGaming for the open-source ANGLE project. Typically one would
label a multi-vendor extension as EXT, but EXT_framebuffer_mulitsample
is already the name for this on Desktop GL. Additionally this
isn't truely a multi-vendor extension because there is only one
implementation of this. We'll follow the example of the open-source
MESA project which uses the project name for the vendor suffix.
2) How does this extension differ from EXT_framebuffer_multisample?
This is designed to be a proper subset of EXT_framebuffer_multisample
functionality as applicable to OpenGL ES 2.0.
Functionality that is unchanged:
- creation of multisample renderbuffers.
- whole buffer multi-sample->single-sample resolve.
- no format conversions, stretching or flipping supported on multisample blits.
Additional restrictions on BlitFramebufferANGLE:
- multisample resolve is only supported on color buffers.
- no blits to multisample destinations (no single->multi or multi-multi).
- only entire buffers can be resolved.
Revision History
Revision 1, 2010/07/08
- copied from revision 7 of EXT_framebuffer_multisample
- removed language that was not relevant to ES2
- rebase changes against the Open GL ES 2.0 specification
- added ANGLE-specific restrictions
Revision 2, 2010/07/19
- fix missing error code
Revision 3, 2010/08/06
- add additional contributors, update implementation status
- disallow negative samples

Просмотреть файл

@ -0,0 +1,591 @@
Name
ANGLE_timer_query
Name Strings
GL_ANGLE_timer_query
Contributors
Contributors to ARB_occlusion_query
Contributors to EXT_timer_query
Contributors to ARB_timer_query
Ben Vanik, Google Inc.
Daniel Koch, TransGaming Inc.
Contact
Ben Vanik, Google Inc. (benvanik 'at' google 'dot' com)
Status
Draft
Version
Last Modified Date: Apr 28, 2011
Author Revision: 1
Number
OpenGL ES Extension #??
Dependencies
OpenGL ES 2.0 is required.
The extension is written against the OpenGL ES 2.0 specification.
Overview
Applications can benefit from accurate timing information in a number of
different ways. During application development, timing information can
help identify application or driver bottlenecks. At run time,
applications can use timing information to dynamically adjust the amount
of detail in a scene to achieve constant frame rates. OpenGL
implementations have historically provided little to no useful timing
information. Applications can get some idea of timing by reading timers
on the CPU, but these timers are not synchronized with the graphics
rendering pipeline. Reading a CPU timer does not guarantee the completion
of a potentially large amount of graphics work accumulated before the
timer is read, and will thus produce wildly inaccurate results.
glFinish() can be used to determine when previous rendering commands have
been completed, but will idle the graphics pipeline and adversely affect
application performance.
This extension provides a query mechanism that can be used to determine
the amount of time it takes to fully complete a set of GL commands, and
without stalling the rendering pipeline. It uses the query object
mechanisms first introduced in the occlusion query extension, which allow
time intervals to be polled asynchronously by the application.
IP Status
No known IP claims.
New Procedures and Functions
void GenQueriesANGLE(sizei n, uint *ids);
void DeleteQueriesANGLE(sizei n, const uint *ids);
boolean IsQueryANGLE(uint id);
void BeginQueryANGLE(enum target, uint id);
void EndQueryANGLE(enum target);
void QueryCounterANGLE(uint id, enum target);
void GetQueryivANGLE(enum target, enum pname, int *params);
void GetQueryObjectivANGLE(uint id, enum pname, int *params);
void GetQueryObjectuivANGLE(uint id, enum pname, uint *params);
void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params);
void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params);
New Tokens
Accepted by the <pname> parameter of GetQueryivANGLE:
QUERY_COUNTER_BITS_ANGLE 0x8864
CURRENT_QUERY_ANGLE 0x8865
Accepted by the <pname> parameter of GetQueryObjectivANGLE,
GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, and
GetQueryObjectui64vANGLE:
QUERY_RESULT_ANGLE 0x8866
QUERY_RESULT_AVAILABLE_ANGLE 0x8867
Accepted by the <target> parameter of BeginQueryANGLE, EndQueryANGLE, and
GetQueryivANGLE:
TIME_ELAPSED_ANGLE 0x88BF
Accepted by the <target> parameter of GetQueryivANGLE and
QueryCounterANGLE:
TIMESTAMP_ANGLE 0x8E28
Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
(Modify table 2.1, Correspondence of command suffix letters to GL argument)
Add two new types:
Letter Corresponding GL Type
------ ---------------------
i64 int64ANGLE
ui64 uint64ANGLE
(Modify table 2.2, GL data types) Add two new types:
GL Type Minimum Bit Width Description
------- ----------------- -----------------------------
int64ANGLE 64 Signed 2's complement integer
uint64ANGLE 64 Unsigned binary integer
Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
Add a new section 5.3 "Timer Queries":
"5.3 Timer Queries
Timer queries use query objects to track the amount of time needed to
fully complete a set of GL commands, or to determine the current time
of the GL.
Timer queries are associated with query objects. The command
void GenQueriesANGLE(sizei n, uint *ids);
returns <n> previously unused query object names in <ids>. These
names are marked as used, but no object is associated with them until
the first time they are used by BeginQueryANGLE. Query objects contain
one piece of state, an integer result value. This result value is
initialized to zero when the object is created. Any positive integer
except for zero (which is reserved for the GL) is a valid query
object name.
Query objects are deleted by calling
void DeleteQueriesANGLE(sizei n, const uint *ids);
<ids> contains <n> names of query objects to be deleted. After a
query object is deleted, its name is again unused. Unused names in
<ids> are silently ignored.
If an active query object is deleted its name immediately becomes unused,
but the underlying object is not deleted until it is no longer active.
A timer query can be started and finished by calling
void BeginQueryANGLE(enum target, uint id);
void EndQueryANGLE(enum target);
where <target> is TIME_ELAPSED_ANGLE. If BeginQueryANGLE is called
with an unused <id>, that name is marked as used and associated with
a new query object.
If BeginQueryANGLE is called with an <id> of zero, if the active query
object name for <target> is non-zero, if <id> is the name of an existing
query object whose type does not match <target>, or if <id> is the active
query object name for any query type, the error INVALID_OPERATION is
generated. If EndQueryANGLE is called while no query with the same target
is in progress, an INVALID_OPERATION error is generated.
When BeginQueryANGLE and EndQueryANGLE are called with a <target> of
TIME_ELAPSED_ANGLE, the GL prepares to start and stop the timer used for
timer queries. The timer is started or stopped when the effects from all
previous commands on the GL client and server state and the framebuffer
have been fully realized. The BeginQueryANGLE and EndQueryANGLE commands
may return before the timer is actually started or stopped. When the timer
query timer is finally stopped, the elapsed time (in nanoseconds) is
written to the corresponding query object as the query result value, and
the query result for that object is marked as available.
If the elapsed time overflows the number of bits, <n>, available to hold
elapsed time, its value becomes undefined. It is recommended, but not
required, that implementations handle this overflow case by saturating at
2^n - 1.
The necessary state is a single bit indicating whether an timer
query is active, the identifier of the currently active timer
query, and a counter keeping track of the time that has passed.
When the command
void QueryCounterANGLE(uint id, enum target);
is called with <target> TIMESTAMP_ANGLE, the GL records the current time
into the corresponding query object. The time is recorded after all
previous commands on the GL client and server state and the framebuffer
have been fully realized. When the time is recorded, the query result for
that object is marked available. QueryCounterANGLE timer queries can be
used within a BeginQueryANGLE / EndQueryANGLE block where the <target> is
TIME_ELAPSED_ANGLE and it does not affect the result of that query object.
The error INVALID_OPERATION is generated if the <id> is already in use
within a BeginQueryANGLE/EndQueryANGLE block."
Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
Requests)
Add a new section 6.1.9 "Timer Queries":
"The command
boolean IsQueryANGLE(uint id);
returns TRUE if <id> is the name of a query object. If <id> is zero,
or if <id> is a non-zero value that is not the name of a query
object, IsQueryANGLE returns FALSE.
Information about a query target can be queried with the command
void GetQueryivANGLE(enum target, enum pname, int *params);
<target> identifies the query target and can be TIME_ELAPSED_ANGLE or
TIMESTAMP_ANGLE for timer queries.
If <pname> is CURRENT_QUERY_ANGLE, the name of the currently active query
for <target>, or zero if no query is active, will be placed in <params>.
If <pname> is QUERY_COUNTER_BITS_ANGLE, the implementation-dependent number
of bits used to hold the query result for <target> will be placed in
<params>. The number of query counter bits may be zero, in which case
the counter contains no useful information.
For timer queries (TIME_ELAPSED_ANGLE and TIMESTAMP_ANGLE), if the number
of bits is non-zero, the minimum number of bits allowed is 30 which
will allow at least 1 second of timing.
The state of a query object can be queried with the commands
void GetQueryObjectivANGLE(uint id, enum pname, int *params);
void GetQueryObjectuivANGLE(uint id, enum pname, uint *params);
void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params);
void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params);
If <id> is not the name of a query object, or if the query object
named by <id> is currently active, then an INVALID_OPERATION error is
generated.
If <pname> is QUERY_RESULT_ANGLE, then the query object's result
value is returned as a single integer in <params>. If the value is so
large in magnitude that it cannot be represented with the requested type,
then the nearest value representable using the requested type is
returned. If the number of query counter bits for target is zero, then
the result is returned as a single integer with the value zero.
There may be an indeterminate delay before the above query returns. If
<pname> is QUERY_RESULT_AVAILABLE_ANGLE, FALSE is returned if such a delay
would be required; otherwise TRUE is returned. It must always be true
that if any query object returns a result available of TRUE, all queries
of the same type issued prior to that query must also return TRUE.
Querying the state for a given timer query forces that timer query to
complete within a finite amount of time.
If multiple queries are issued on the same target and id prior to
calling GetQueryObject[u]i[64]vANGLE, the result returned will always be
from the last query issued. The results from any queries before the
last one will be lost if the results are not retrieved before starting
a new query on the same <target> and <id>."
Errors
The error INVALID_VALUE is generated if GenQueriesANGLE is called where
<n> is negative.
The error INVALID_VALUE is generated if DeleteQueriesANGLE is called
where <n> is negative.
The error INVALID_OPERATION is generated if BeginQueryANGLE is called
when a query of the given <target> is already active.
The error INVALID_OPERATION is generated if EndQueryANGLE is called
when a query of the given <target> is not active.
The error INVALID_OPERATION is generated if BeginQueryANGLE is called
where <id> is zero.
The error INVALID_OPERATION is generated if BeginQueryANGLE is called
where <id> is the name of a query currently in progress.
The error INVALID_OPERATION is generated if BeginQueryANGLE is called
where <id> is the name of an existing query object whose type does not
match <target>.
The error INVALID_ENUM is generated if BeginQueryANGLE or EndQueryANGLE
is called where <target> is not TIME_ELAPSED_ANGLE.
The error INVALID_ENUM is generated if GetQueryivANGLE is called where
<target> is not TIME_ELAPSED_ANGLE or TIMESTAMP_ANGLE.
The error INVALID_ENUM is generated if GetQueryivANGLE is called where
<pname> is not QUERY_COUNTER_BITS_ANGLE or CURRENT_QUERY_ANGLE.
The error INVALID_ENUM is generated if QueryCounterANGLE is called where
<target> is not TIMESTAMP_ANGLE.
The error INVALID_OPERATION is generated if QueryCounterANGLE is called
on a query object that is already in use inside a
BeginQueryANGLE/EndQueryANGLE.
The error INVALID_OPERATION is generated if GetQueryObjectivANGLE,
GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
GetQueryObjectui64vANGLE is called where <id> is not the name of a query
object.
The error INVALID_OPERATION is generated if GetQueryObjectivANGLE,
GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
GetQueryObjectui64vANGLE is called where <id> is the name of a currently
active query object.
The error INVALID_ENUM is generated if GetQueryObjectivANGLE,
GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
GetQueryObjectui64vANGLE is called where <pname> is not
QUERY_RESULT_ANGLE or QUERY_RESULT_AVAILABLE_ANGLE.
New State
(Add a new table 6.xx, "Query Operations")
Get Value Type Get Command Initial Value Description Sec
--------- ---- ----------- ------------- ----------- ------
- B - FALSE query active 5.3
CURRENT_QUERY_ANGLE Z+ GetQueryivANGLE 0 active query ID 5.3
QUERY_RESULT_ANGLE Z+ GetQueryObjectuivANGLE, 0 samples-passed count 5.3
GetQueryObjectui64vANGLE
QUERY_RESULT_AVAILABLE_ANGLE B GetQueryObjectivANGLE FALSE query result available 5.3
New Implementation Dependent State
(Add the following entry to table 6.18):
Get Value Type Get Command Minimum Value Description Sec
-------------------------- ---- ----------- ------------- ---------------- ------
QUERY_COUNTER_BITS_ANGLE Z+ GetQueryivANGLE see 6.1.9 Number of bits in 6.1.9
query counter
Examples
(1) Here is some rough sample code that demonstrates the intended usage
of this extension.
GLint queries[N];
GLint available = 0;
// timer queries can contain more than 32 bits of data, so always
// query them using the 64 bit types to avoid overflow
GLuint64ANGLE timeElapsed = 0;
// Create a query object.
glGenQueriesANGLE(N, queries);
// Start query 1
glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[0]);
// Draw object 1
....
// End query 1
glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE);
...
// Start query N
glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[N-1]);
// Draw object N
....
// End query N
glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE);
// Wait for all results to become available
while (!available) {
glGetQueryObjectivANGLE(queries[N-1], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available);
}
for (i = 0; i < N; i++) {
// See how much time the rendering of object i took in nanoseconds.
glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeElapsed);
// Do something useful with the time. Note that care should be
// taken to use all significant bits of the result, not just the
// least significant 32 bits.
AdjustObjectLODBasedOnDrawTime(i, timeElapsed);
}
This example is sub-optimal in that it stalls at the end of every
frame to wait for query results. Ideally, the collection of results
would be delayed one frame to minimize the amount of time spent
waiting for the GPU to finish rendering.
(2) This example is basically the same as the example above but uses
QueryCounter instead.
GLint queries[N+1];
GLint available = 0;
// timer queries can contain more than 32 bits of data, so always
// query them using the 64 bit types to avoid overflow
GLuint64ANGLE timeStart, timeEnd, timeElapsed = 0;
// Create a query object.
glGenQueriesANGLE(N+1, queries);
// Query current timestamp 1
glQueryCounterANGLE(queries[0], GL_TIMESTAMP_ANGLE);
// Draw object 1
....
// Query current timestamp N
glQueryCounterANGLE(queries[N-1], GL_TIMESTAMP_ANGLE);
// Draw object N
....
// Query current timestamp N+1
glQueryCounterANGLE(queries[N], GL_TIMESTAMP_ANGLE);
// Wait for all results to become available
while (!available) {
glGetQueryObjectivANGLE(queries[N], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available);
}
for (i = 0; i < N; i++) {
// See how much time the rendering of object i took in nanoseconds.
glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeStart);
glGetQueryObjectui64vANGLE(queries[i+1], GL_QUERY_RESULT_ANGLE, &timeEnd);
timeElapsed = timeEnd - timeStart;
// Do something useful with the time. Note that care should be
// taken to use all significant bits of the result, not just the
// least significant 32 bits.
AdjustObjectLODBasedOnDrawTime(i, timeElapsed);
}
Issues from EXT_timer_query
(1) What time interval is being measured?
RESOLVED: The timer starts when all commands prior to BeginQuery() have
been fully executed. At that point, everything that should be drawn by
those commands has been written to the framebuffer. The timer stops
when all commands prior to EndQuery() have been fully executed.
(2) What unit of time will time intervals be returned in?
RESOLVED: Nanoseconds (10^-9 seconds). This unit of measurement allows
for reasonably accurate timing of even small blocks of rendering
commands. The granularity of the timer is implementation-dependent. A
32-bit query counter can express intervals of up to approximately 4
seconds.
(3) What should be the minimum number of counter bits for timer queries?
RESOLVED: 30 bits, which will allow timing sections that take up to 1
second to render.
(4) How are counter results of more than 32 bits returned?
RESOLVED: Via two new datatypes, int64ANGLE and uint64ANGLE, and their
corresponding GetQueryObject entry points. These types hold integer
values and have a minimum bit width of 64.
(5) Should the extension measure total time elapsed between the full
completion of the BeginQuery and EndQuery commands, or just time
spent in the graphics library?
RESOLVED: This extension will measure the total time elapsed between
the full completion of these commands. Future extensions may implement
a query to determine time elapsed at different stages of the graphics
pipeline.
(6) If multiple query types are supported, can multiple query types be
active simultaneously?
RESOLVED: Yes; an application may perform a timer query and another
type of query simultaneously. An application can not perform multiple
timer queries or multiple queries of other types simultaneously. An
application also can not use the same query object for another query
and a timer query simultaneously.
(7) Do query objects have a query type permanently associated with them?
RESOLVED: No. A single query object can be used to perform different
types of queries, but not at the same time.
Having a fixed type for each query object simplifies some aspects of the
implementation -- not having to deal with queries with different result
sizes, for example. It would also mean that BeginQuery() with a query
object of the "wrong" type would result in an INVALID_OPERATION error.
UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0.
Since EXT_transform_feedback has since been incorporated into the core,
the resolution is that BeginQuery will generate error INVALID_OPERATION
if <id> represents a query object of a different type.
(8) How predictable/repeatable are the results returned by the timer
query?
RESOLVED: In general, the amount of time needed to render the same
primitives should be fairly constant. But there may be many other
system issues (e.g., context switching on the CPU and GPU, virtual
memory page faults, memory cache behavior on the CPU and GPU) that can
cause times to vary wildly.
Note that modern GPUs are generally highly pipelined, and may be
processing different primitives in different pipeline stages
simultaneously. In this extension, the timers start and stop when the
BeginQuery/EndQuery commands reach the bottom of the rendering pipeline.
What that means is that by the time the timer starts, the GL driver on
the CPU may have started work on GL commands issued after BeginQuery,
and the higher pipeline stages (e.g., vertex transformation) may have
started as well.
(9) What should the new 64 bit integer type be called?
RESOLVED: The new types will be called GLint64ANGLE/GLuint64ANGLE. The new
command suffixes will be i64 and ui64. These names clearly convey the
minimum size of the types. These types are similar to the C99 standard
type int_least64_t, but we use names similar to the C99 optional type
int64_t for simplicity.
Issues from ARB_timer_query
(10) What about tile-based implementations? The effects of a command are
not complete until the frame is completely rendered. Timing recorded
before the frame is complete may not be what developers expect. Also
the amount of time needed to render the same primitives is not
consistent, which conflicts with issue (8) above. The time depends on
how early or late in the scene it is placed.
RESOLVED: The current language supports tile-based rendering okay as it
is written. Developers are warned that using timers on tile-based
implementation may not produce results they expect since rendering is not
done in a linear order. Timing results are calculated when the frame is
completed and may depend on how early or late in the scene it is placed.
(11) Can the GL implementation use different clocks to implement the
TIME_ELAPSED and TIMESTAMP queries?
RESOLVED: Yes, the implemenation can use different internal clocks to
implement TIME_ELAPSED and TIMESTAMP. If different clocks are
used it is possible there is a slight discrepancy when comparing queries
made from TIME_ELAPSED and TIMESTAMP; they may have slight
differences when both are used to measure the same sequence. However, this
is unlikely to affect real applications since comparing the two queries is
not expected to be useful.
Issues
(12) What should we call this extension?
RESOLVED: ANGLE_timer_query
(13) Why is this done as a separate extension instead of just supporting
ARB_timer_query?
ARB_timer_query is written against OpenGL 3.2, which includes a lot of
the required support for dealing with query objects. None of these
functions or tokens exist in OpenGL ES, and as such have to be added in
this specification.
(14) How does this extension differ from ARB_timer_query?
This extension contains most ARB_timer_query behavior unchanged as well
as a subset of the query support required to use it from the core
OpenGL 3.2 spec. It omits the glGetInteger(TIMESTAMP) functionality used to
query the current time on the GPU, but the behavior for all remaining
functionality taken from ARB_timer_query is the same.
(15) Are query objects shareable between multiple contexts?
RESOLVED: No. Query objects are lightweight and we normally share
large data across contexts. Also, being able to share query objects
across contexts is not particularly useful. In order to do the async
query across contexts, a query on one context would have to be finished
before the other context could query it.
Revision History
Revision 1, 2011/04/28
- copied from revision 9 of ARB_timer_query and revision 7 of
ARB_occlusion_query
- removed language that was clearly not relevant to ES2
- rebased changes against the OpenGL ES 2.0 specification

Просмотреть файл

@ -0,0 +1,98 @@
Name
ANGLE_d3d_share_handle_client_buffer
Name Strings
EGL_ANGLE_d3d_share_handle_client_buffer
Contributors
John Bauman
Alastair Patrick
Daniel Koch
Contacts
John Bauman, Google Inc. (jbauman 'at' chromium.org)
Status
Complete
Implemented (ANGLE r650)
Version
Version 3, May 12, 2011
Number
EGL Extension #??
Dependencies
Requires the EGL_ANGLE_surface_d3d_texture_2d_share_handle extension.
This extension is written against the wording of the EGL 1.4
Specification.
Overview
This extension allows creating EGL surfaces from handles to textures
shared from the Direct3D API or from
EGL_ANGLE_surface_texture_2d_share_handle.
New Types
None
New Procedures and Functions
None
New Tokens
Accepted in the <buftype> parameter of eglCreatePbufferFromClientBuffer:
EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
Replace the last sentence of paragraph 1 of Section 3.5.3 with the
following text.
"Currently, the only client API resources which may be bound in this
fashion are OpenVG VGImage objects and Direct3D share handles."
Replace the last sentence of paragraph 2 ("To bind a client API...") of
Section 3.5.3 with the following text.
"When <buftype> is EGL_OPENVG_IMAGE, the width and height of the pbuffer
are determined by the width and height of <buffer>. When <buftype> is
EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, the width and height are specified
using EGL_WIDTH and EGL_HEIGHT, or else they default to zero. The width
and height must match the dimensions of the texture which the share handle
was created from or else an EGL_BAD_ALLOC error is generated."
Replace the third paragraph of Section 3.5.3 with the following text.
"<buftype> specifies the type of buffer to be bound. The only allowed values
of <buftype> are EGL_OPENVG_IMAGE and
EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE".
Append the following text to the fourth paragraph of Section 3.5.3.
"When <buftype> is EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, <buffer> must be
a valid D3D share handle, cast into the type EGLClientBuffer. The handle
may be obtained from the Direct3D9Ex CreateTexture function, from DXGI's
GetSharedHandle method on an ID3D10Texture2D, or from the
EGL_ANGLE_surface_d3d_texture_2d_share_handle extension."
Issues
Revision History
Version 3, 2011/05/12
- publish
Version 2, 2011/05/03
- specify EGL_D3D_TEXTURE_2D_SHARE_HANDLE
- specify error if dimensions don't match
Version 1, 2011/04/12 - first draft.

Просмотреть файл

@ -0,0 +1,88 @@
Name
ANGLE_query_surface_pointer
Name Strings
EGL_ANGLE_query_surface_pointer
Contributors
Vladimir Vukicevic
Daniel Koch
Contacts
Vladimir Vukicevic (vladimir 'at' pobox.com)
Status
Complete
Implemented (ANGLE r558)
Version
Version 3, February 11, 2011
Number
EGL Extension #??
Dependencies
This extension is written against the wording of the EGL 1.4
Specification.
Overview
This extension allows querying pointer-sized surface attributes,
thus avoiding problems with coercing 64-bit pointers into a 32-bit
integer.
New Types
None
New Procedures and Functions
EGLBoolean eglQuerySurfacePointerANGLE(
EGLDisplay dpy,
EGLSurface surface,
EGLint attribute,
void **value);
New Tokens
None
Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
Add to the end of the paragraph starting with "To query an
attribute associated with an EGLSurface" in section 3.5.6,
"Surface Attributes":
"If the attribute type in table 3.5 is 'pointer', then
eglQuerySurface returns EGL_FALSE and an EGL_BAD_PARAMETER error
is generated. To query pointer attributes, call:
EGLBoolean eglQuerySurfacePointerANGLE(
EGLDisplay dpy,
EGLSurface surface,
EGLint attribute,
void **value);
eglQuerySurfacePointerANGLE behaves identically to eglQuerySurface,
except that only attributes of type 'pointer' can be queried.
If an attribute queried via eglQuerySurfacePointerANGLE is not
of type 'pointer', then eglQuerySurfacePointer returns EGL_FALSE
and an EGL_BAD_PARAMETER error is generated."
Issues
Revision History
Version 3, 2011/02/11 - publish
Version 2, 2010/12/21 - fix typos.
Version 1, 2010/12/07 - first draft.

Просмотреть файл

@ -0,0 +1,95 @@
Name
ANGLE_surface_d3d_texture_2d_share_handle
Name Strings
EGL_ANGLE_surface_d3d_texture_2d_share_handle
Contributors
Vladimir Vukicevic
Daniel Koch
Contacts
Vladimir Vukicevic (vladimir 'at' pobox.com)
Status
Complete
Implemented (ANGLE r558)
Version
Version 2, December 21, 2010
Number
EGL Extension #??
Dependencies
Requires the EGL_ANGLE_query_surface_pointer extension.
This extension is written against the wording of the EGL 1.4
Specification.
Overview
Some EGL implementations generate EGLSurface handles that are
backed by Direct3D 2D textures. For such surfaces, a D3D share
handle can be generated, allowing access to the same surface
from the Direct3D API.
New Types
None
New Procedures and Functions
None
New Tokens
Accepted in the <attribute> parameter of eglQuerySurfacePointerANGLE:
EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
Add to table 3.5, "Queryable surface attributes and types":
Attribute Type Description
--------- ---- -----------
EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE pointer Direct3D share handle
Add before the last paragraph in section 3.5, "Surface attributes":
"Querying EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE returns a Direct3D
share handle, or NULL if a share handle for the surface is not
available. The share handle must be queried using
eglQuerySurfaceAttribPointerANGLE. Before using a Direct3D surface
created with this share handle, ensure that all rendering
to the EGLSurface with EGL client APIs has completed.
The Direct3D share handle may be passed as the pSharedHandle
parameter of the Direct3D9Ex CreateTexture function, or via the
Direct3D10 OpenSharedResource function. If used with Direct3D 9,
the level argument to CreateTexture must be 1, and the dimensions
must match the dimensions of the EGL surface. If used with
Direct3D 10, OpenSharedResource should be called with the
ID3D10Texture2D uuid to obtain an ID3D10Texture2D object.
Issues
Revision History
Version 3, 2011/02/11 - publish
Version 2, 2010/12/21
- renamed token to EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE (adding "2D")
- renamed extension to ANGLE_surface_d3d_texture_2d_share_handle
- added language about supported usage of the shared handle from D3D
Version 1, 2010/12/07 - first draft.

Просмотреть файл

@ -223,9 +223,9 @@ EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
#endif
#ifndef EGL_ANGLE_surface_d3d_share_handle
#define EGL_ANGLE_surface_d3d_share_handle
#define EGL_D3D_TEXTURE_SHARE_HANDLE_ANGLE 0x3200
#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
#endif
#ifdef __cplusplus

Просмотреть файл

@ -17,7 +17,7 @@ extern "C" {
// Version number for shader translation API.
// It is incremented everytime the API changes.
#define SH_VERSION 103
#define SH_VERSION 104
//
// The names of the following enums have been derived by replacing GL prefix
@ -62,7 +62,8 @@ typedef enum {
SH_ACTIVE_UNIFORMS = 0x8B86,
SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
SH_ACTIVE_ATTRIBUTES = 0x8B89,
SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A
SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
SH_MAPPED_NAME_MAX_LENGTH = 0x8B8B
} ShShaderInfo;
// Compile options.
@ -73,7 +74,8 @@ typedef enum {
SH_OBJECT_CODE = 0x0004,
SH_ATTRIBUTES_UNIFORMS = 0x0008,
SH_LINE_DIRECTIVES = 0x0010,
SH_SOURCE_PATH = 0x0200
SH_SOURCE_PATH = 0x0020,
SH_MAP_LONG_VARIABLE_NAMES = 0x0040
} ShCompileOptions;
//
@ -185,6 +187,8 @@ int ShCompile(
// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
// variable name including the null
// termination character.
// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
// the null termination character.
//
// params: Requested parameter
void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params);
@ -223,12 +227,18 @@ void ShGetObjectCode(const ShHandle handle, char* objCode);
// accomodate the attribute variable name. The size of the buffer
// required to store the attribute variable name can be obtained by
// calling ShGetInfo with SH_ACTIVE_ATTRIBUTE_MAX_LENGTH.
// mappedName: Returns a null terminated string containing the mapped name of
// the attribute variable, It is assumed that mappedName has enough
// memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
// about the mapped name. If the name is not mapped, then name and
// mappedName are the same.
void ShGetActiveAttrib(const ShHandle handle,
int index,
int* length,
int* size,
ShDataType* type,
char* name);
char* name,
char* mappedName);
// Returns information about an active uniform variable.
// Parameters:
@ -244,12 +254,18 @@ void ShGetActiveAttrib(const ShHandle handle,
// accomodate the uniform variable name. The size of the buffer required
// to store the uniform variable name can be obtained by calling
// ShGetInfo with SH_ACTIVE_UNIFORMS_MAX_LENGTH.
// mappedName: Returns a null terminated string containing the mapped name of
// the uniform variable, It is assumed that mappedName has enough
// memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
// about the mapped name. If the name is not mapped, then name and
// mappedName are the same.
void ShGetActiveUniform(const ShHandle handle,
int index,
int* length,
int* size,
ShDataType* type,
char* name);
char* name,
char* mappedName);
#ifdef __cplusplus
}

Просмотреть файл

@ -231,10 +231,10 @@ void PrintActiveVariables(ShHandle compiler, ShShaderInfo varType)
for (int i = 0; i < activeVars; ++i) {
switch (varType) {
case SH_ACTIVE_ATTRIBUTES:
ShGetActiveAttrib(compiler, i, NULL, &size, &type, name);
ShGetActiveAttrib(compiler, i, NULL, &size, &type, name, NULL);
break;
case SH_ACTIVE_UNIFORMS:
ShGetActiveUniform(compiler, i, NULL, &size, &type, name);
ShGetActiveUniform(compiler, i, NULL, &size, &type, name, NULL);
break;
default: assert(0);
}

Просмотреть файл

@ -6,6 +6,7 @@
'target_defaults': {
'defines': [
'ANGLE_DISABLE_TRACE',
'ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0',
],
},
'targets': [
@ -40,6 +41,8 @@
'compiler/intermOut.cpp',
'compiler/IntermTraverse.cpp',
'compiler/localintermediate.h',
'compiler/MapLongVariableNames.cpp',
'compiler/MapLongVariableNames.h',
'compiler/MMap.h',
'compiler/osinclude.h',
'compiler/parseConst.cpp',
@ -99,6 +102,8 @@
],
'sources': [
'compiler/CodeGenGLSL.cpp',
'compiler/ForLoopUnroll.cpp',
'compiler/ForLoopUnroll.h',
'compiler/OutputGLSL.cpp',
'compiler/OutputGLSL.h',
'compiler/TranslatorGLSL.cpp',
@ -145,11 +150,11 @@
'common/debug.cpp',
'common/debug.h',
'common/version.h',
'libGLESv2/geometry/IndexDataManager.cpp',
'libGLESv2/geometry/IndexDataManager.h',
'libGLESv2/geometry/vertexconversion.h',
'libGLESv2/geometry/VertexDataManager.cpp',
'libGLESv2/geometry/VertexDataManager.h',
'libGLESv2/IndexDataManager.cpp',
'libGLESv2/IndexDataManager.h',
'libGLESv2/vertexconversion.h',
'libGLESv2/VertexDataManager.cpp',
'libGLESv2/VertexDataManager.h',
'libGLESv2/Blit.cpp',
'libGLESv2/Blit.h',
'libGLESv2/Buffer.cpp',
@ -160,6 +165,8 @@
'libGLESv2/Fence.h',
'libGLESv2/Framebuffer.cpp',
'libGLESv2/Framebuffer.h',
'libGLESv2/HandleAllocator.cpp',
'libGLESv2/HandleAllocator.h',
'libGLESv2/libGLESv2.cpp',
'libGLESv2/libGLESv2.def',
'libGLESv2/main.cpp',
@ -186,6 +193,7 @@
'AdditionalDependencies': [
'd3d9.lib',
'd3dx9.lib',
'd3dcompiler.lib',
],
}
},

Просмотреть файл

@ -72,7 +72,8 @@ bool perfActive()
#if defined(ANGLE_DISABLE_PERF)
return false;
#else
return D3DPERF_GetStatus() != 0;
static bool active = D3DPERF_GetStatus() != 0;
return active;
#endif
}

Просмотреть файл

@ -63,7 +63,7 @@ namespace gl
#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
#define EVENT(message, ...) (void(0))
#else
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s\n" message, __FUNCTION__, __VA_ARGS__);
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__);
#endif
// A macro asserting a condition and outputting failures to the debug log

Просмотреть файл

@ -1,7 +1,7 @@
#define MAJOR_VERSION 0
#define MINOR_VERSION 0
#define BUILD_VERSION 0
#define BUILD_REVISION 611
#define BUILD_REVISION 653
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)

Просмотреть файл

@ -8,6 +8,7 @@
#include "compiler/ParseHelper.h"
#include "compiler/ShHandle.h"
#include "compiler/ValidateLimitations.h"
#include "compiler/MapLongVariableNames.h"
namespace {
bool InitializeSymbolTable(
@ -147,14 +148,20 @@ bool TCompiler::compile(const char* const shaderStrings[],
if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
success = validateLimitations(root);
// Call mapLongVariableNames() before collectAttribsUniforms() so in
// collectAttribsUniforms() we already have the mapped symbol names and
// we could composite mapped and original variable names.
if (compileOptions & SH_MAP_LONG_VARIABLE_NAMES)
mapLongVariableNames(root);
if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
collectAttribsUniforms(root);
if (success && (compileOptions & SH_INTERMEDIATE_TREE))
intermediate.outputTree(root);
if (success && (compileOptions & SH_OBJECT_CODE))
translate(root);
if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
collectAttribsUniforms(root);
}
// Cleanup memory.
@ -197,3 +204,14 @@ void TCompiler::collectAttribsUniforms(TIntermNode* root)
CollectAttribsUniforms collect(attribs, uniforms);
root->traverse(&collect);
}
void TCompiler::mapLongVariableNames(TIntermNode* root)
{
MapLongVariableNames map;
root->traverse(&map);
}
int TCompiler::getMappedNameMaxLength() const
{
return MAX_IDENTIFIER_NAME_SIZE + 1;
}

Просмотреть файл

@ -26,26 +26,17 @@ public:
bool operator==(const int i) const
{
if (i == iConst)
return true;
return false;
return i == iConst;
}
bool operator==(const float f) const
{
if (f == fConst)
return true;
return false;
return f == fConst;
}
bool operator==(const bool b) const
{
if (b == bConst)
return true;
return false;
return b == bConst;
}
bool operator==(const ConstantUnion& constant) const
@ -55,20 +46,13 @@ public:
switch (type) {
case EbtInt:
if (constant.iConst == iConst)
return true;
break;
return constant.iConst == iConst;
case EbtFloat:
if (constant.fConst == fConst)
return true;
break;
return constant.fConst == fConst;
case EbtBool:
if (constant.bConst == bConst)
return true;
break;
return constant.bConst == bConst;
default:
return false;
}
return false;
@ -99,18 +83,11 @@ public:
assert(type == constant.type);
switch (type) {
case EbtInt:
if (iConst > constant.iConst)
return true;
return false;
return iConst > constant.iConst;
case EbtFloat:
if (fConst > constant.fConst)
return true;
return false;
return fConst > constant.fConst;
default:
assert(false && "Default missing");
return false;
return false; // Invalid operation, handled at semantic analysis
}
return false;
@ -121,18 +98,11 @@ public:
assert(type == constant.type);
switch (type) {
case EbtInt:
if (iConst < constant.iConst)
return true;
return false;
return iConst < constant.iConst;
case EbtFloat:
if (fConst < constant.fConst)
return true;
return false;
return fConst < constant.fConst;
default:
assert(false && "Default missing");
return false;
return false; // Invalid operation, handled at semantic analysis
}
return false;

Просмотреть файл

@ -0,0 +1,172 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/ForLoopUnroll.h"
void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info)
{
ASSERT(node->getType() == ELoopFor);
ASSERT(node->getUnrollFlag());
TIntermNode* init = node->getInit();
ASSERT(init != NULL);
TIntermAggregate* decl = init->getAsAggregate();
ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration));
TIntermSequence& declSeq = decl->getSequence();
ASSERT(declSeq.size() == 1);
TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize));
TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
ASSERT(symbol != NULL);
ASSERT(symbol->getBasicType() == EbtInt);
info.id = symbol->getId();
ASSERT(declInit->getRight() != NULL);
TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
ASSERT(initNode != NULL);
info.initValue = evaluateIntConstant(initNode);
info.currentValue = info.initValue;
TIntermNode* cond = node->getCondition();
ASSERT(cond != NULL);
TIntermBinary* binOp = cond->getAsBinaryNode();
ASSERT(binOp != NULL);
ASSERT(binOp->getRight() != NULL);
ASSERT(binOp->getRight()->getAsConstantUnion() != NULL);
info.incrementValue = getLoopIncrement(node);
info.stopValue = evaluateIntConstant(
binOp->getRight()->getAsConstantUnion());
info.op = binOp->getOp();
}
void ForLoopUnroll::Step()
{
ASSERT(mLoopIndexStack.size() > 0);
TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
info.currentValue += info.incrementValue;
}
bool ForLoopUnroll::SatisfiesLoopCondition()
{
ASSERT(mLoopIndexStack.size() > 0);
TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
// Relational operator is one of: > >= < <= == or !=.
switch (info.op) {
case EOpEqual:
return (info.currentValue == info.stopValue);
case EOpNotEqual:
return (info.currentValue != info.stopValue);
case EOpLessThan:
return (info.currentValue < info.stopValue);
case EOpGreaterThan:
return (info.currentValue > info.stopValue);
case EOpLessThanEqual:
return (info.currentValue <= info.stopValue);
case EOpGreaterThanEqual:
return (info.currentValue >= info.stopValue);
default:
UNREACHABLE();
}
return false;
}
bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol)
{
for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
i != mLoopIndexStack.end();
++i) {
if (i->id == symbol->getId())
return true;
}
return false;
}
int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol)
{
for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
i != mLoopIndexStack.end();
++i) {
if (i->id == symbol->getId())
return i->currentValue;
}
UNREACHABLE();
return false;
}
void ForLoopUnroll::Push(TLoopIndexInfo& info)
{
mLoopIndexStack.push_back(info);
}
void ForLoopUnroll::Pop()
{
mLoopIndexStack.pop_back();
}
int ForLoopUnroll::getLoopIncrement(TIntermLoop* node)
{
TIntermNode* expr = node->getExpression();
ASSERT(expr != NULL);
// for expression has one of the following forms:
// loop_index++
// loop_index--
// loop_index += constant_expression
// loop_index -= constant_expression
// ++loop_index
// --loop_index
// The last two forms are not specified in the spec, but I am assuming
// its an oversight.
TIntermUnary* unOp = expr->getAsUnaryNode();
TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
TOperator op = EOpNull;
TIntermConstantUnion* incrementNode = NULL;
if (unOp != NULL) {
op = unOp->getOp();
} else if (binOp != NULL) {
op = binOp->getOp();
ASSERT(binOp->getRight() != NULL);
incrementNode = binOp->getRight()->getAsConstantUnion();
ASSERT(incrementNode != NULL);
}
int increment = 0;
// The operator is one of: ++ -- += -=.
switch (op) {
case EOpPostIncrement:
case EOpPreIncrement:
ASSERT((unOp != NULL) && (binOp == NULL));
increment = 1;
break;
case EOpPostDecrement:
case EOpPreDecrement:
ASSERT((unOp != NULL) && (binOp == NULL));
increment = -1;
break;
case EOpAddAssign:
ASSERT((unOp == NULL) && (binOp != NULL));
increment = evaluateIntConstant(incrementNode);
break;
case EOpSubAssign:
ASSERT((unOp == NULL) && (binOp != NULL));
increment = - evaluateIntConstant(incrementNode);
break;
default:
ASSERT(false);
}
return increment;
}
int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node)
{
ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL));
return node->getUnionArrayPointer()->getIConst();
}

Просмотреть файл

@ -0,0 +1,46 @@
//
// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/intermediate.h"
struct TLoopIndexInfo {
int id;
int initValue;
int stopValue;
int incrementValue;
TOperator op;
int currentValue;
};
class ForLoopUnroll {
public:
ForLoopUnroll() { }
void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info);
// Update the info.currentValue for the next loop iteration.
void Step();
// Return false if loop condition is no longer satisfied.
bool SatisfiesLoopCondition();
// Check if the symbol is the index of a loop that's unrolled.
bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol);
// Return the current value of a given loop index symbol.
int GetLoopIndexValue(TIntermSymbol* symbol);
void Push(TLoopIndexInfo& info);
void Pop();
private:
int getLoopIncrement(TIntermLoop* node);
int evaluateIntConstant(TIntermConstantUnion* node);
TVector<TLoopIndexInfo> mLoopIndexStack;
};

Просмотреть файл

@ -353,7 +353,6 @@ static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources)
//
// Texture Functions.
//
if (resources.MaxVertexTextureImageUnits > 0) {
s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
@ -363,7 +362,6 @@ static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources)
s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);"));
s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);"));
s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);"));
}
return s;
}

Просмотреть файл

@ -1005,8 +1005,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
case EOpAddAssign:
case EOpSubAssign:
case EOpDivAssign:
if (left->isMatrix() && right->isVector() ||
left->isVector() && right->isMatrix())
if ((left->isMatrix() && right->isVector()) ||
(left->isVector() && right->isMatrix()))
return false;
setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
break;
@ -1017,8 +1017,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
if (left->isMatrix() && right->isVector() ||
left->isVector() && right->isMatrix())
if ((left->isMatrix() && right->isVector()) ||
(left->isVector() && right->isMatrix()))
return false;
setType(TType(EbtBool, EbpUndefined));
break;

Просмотреть файл

@ -0,0 +1,61 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/MapLongVariableNames.h"
namespace {
TString mapLongName(int id, const TString& name)
{
ASSERT(name.size() > MAX_IDENTIFIER_NAME_SIZE);
TStringStream stream;
stream << "webgl_" << id << "_";
stream << name.substr(0, MAX_IDENTIFIER_NAME_SIZE - stream.str().size());
return stream.str();
}
} // anonymous namespace
void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol)
{
ASSERT(symbol != NULL);
if (symbol->getSymbol().size() > MAX_IDENTIFIER_NAME_SIZE)
symbol->setSymbol(mapLongName(symbol->getId(), symbol->getSymbol()));
}
void MapLongVariableNames::visitConstantUnion(TIntermConstantUnion*)
{
}
bool MapLongVariableNames::visitBinary(Visit, TIntermBinary*)
{
return true;
}
bool MapLongVariableNames::visitUnary(Visit, TIntermUnary*)
{
return true;
}
bool MapLongVariableNames::visitSelection(Visit, TIntermSelection*)
{
return true;
}
bool MapLongVariableNames::visitAggregate(Visit, TIntermAggregate* node)
{
return true;
}
bool MapLongVariableNames::visitLoop(Visit, TIntermLoop*)
{
return true;
}
bool MapLongVariableNames::visitBranch(Visit, TIntermBranch*)
{
return true;
}

Просмотреть файл

@ -0,0 +1,34 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_MAP_LONG_VARIABLE_NAMES_H_
#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_
#include "GLSLANG/ShaderLang.h"
#include "compiler/intermediate.h"
#include "compiler/VariableInfo.h"
// This size does not include '\0' in the end.
#define MAX_IDENTIFIER_NAME_SIZE 32
// Traverses intermediate tree to map attributes and uniforms names that are
// longer than MAX_IDENTIFIER_NAME_SIZE to MAX_IDENTIFIER_NAME_SIZE.
class MapLongVariableNames : public TIntermTraverser {
public:
MapLongVariableNames() { }
virtual void visitSymbol(TIntermSymbol*);
virtual void visitConstantUnion(TIntermConstantUnion*);
virtual bool visitBinary(Visit, TIntermBinary*);
virtual bool visitUnary(Visit, TIntermUnary*);
virtual bool visitSelection(Visit, TIntermSelection*);
virtual bool visitAggregate(Visit, TIntermAggregate*);
virtual bool visitLoop(Visit, TIntermLoop*);
virtual bool visitBranch(Visit, TIntermBranch*);
};
#endif // COMPILER_MAP_LONG_VARIABLE_NAMES_H_

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -195,6 +195,9 @@ const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type,
void TOutputGLSL::visitSymbol(TIntermSymbol* node)
{
TInfoSinkBase& out = objSink();
if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
out << mLoopUnroll.GetLoopIndexValue(node);
else
out << node->getSymbol();
if (mDeclaringVariables && node->getType().isArray())
@ -615,6 +618,7 @@ bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
TLoopType loopType = node->getType();
if (loopType == ELoopFor) // for loop
{
if (!node->getUnrollFlag()) {
out << "for (";
if (node->getInit())
node->getInit()->traverse(this);
@ -628,6 +632,7 @@ bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
node->getExpression()->traverse(this);
out << ")\n";
}
}
else if (loopType == ELoopWhile) // while loop
{
out << "while (";
@ -642,7 +647,22 @@ bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
}
// Loop body.
if (node->getUnrollFlag())
{
TLoopIndexInfo indexInfo;
mLoopUnroll.FillLoopIndexInfo(node, indexInfo);
mLoopUnroll.Push(indexInfo);
while (mLoopUnroll.SatisfiesLoopCondition())
{
visitCodeBlock(node->getBody());
mLoopUnroll.Step();
}
mLoopUnroll.Pop();
}
else
{
visitCodeBlock(node->getBody());
}
// Loop footer.
if (loopType == ELoopDoWhile) // do-while loop

Просмотреть файл

@ -9,6 +9,7 @@
#include <set>
#include "compiler/ForLoopUnroll.h"
#include "compiler/intermediate.h"
#include "compiler/ParseHelper.h"
@ -44,6 +45,8 @@ private:
// declared only once.
typedef std::set<TString> DeclaredStructs;
DeclaredStructs mDeclaredStructs;
ForLoopUnroll mLoopUnroll;
};
#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -33,8 +33,11 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr
mUsesTexture2D_bias = false;
mUsesTexture2DProj = false;
mUsesTexture2DProj_bias = false;
mUsesTexture2DProjLod = false;
mUsesTexture2DLod = false;
mUsesTextureCube = false;
mUsesTextureCube_bias = false;
mUsesTextureCubeLod = false;
mUsesDepthRange = false;
mUsesFragCoord = false;
mUsesPointCoord = false;
@ -345,6 +348,84 @@ void OutputHLSL::header()
"\n";
out << uniforms;
out << "\n";
// The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored
// according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0)
// is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D
// convention, the Y coordinate passed to these functions is adjusted to compensate.
//
// The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0].
//
// The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3
// case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0].
//
// For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the
// +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the
// +Y and -Y faces everywhere else throughout the code.
if (mUsesTexture2D)
{
out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
"{\n"
" return tex2Dlod(s, float4(t.x, 1 - t.y, 0, 0));\n"
"}\n"
"\n";
}
if (mUsesTexture2DLod)
{
out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n"
"{\n"
" return tex2Dlod(s, float4(t.x, 1 - t.y, 0, lod));\n"
"}\n"
"\n";
}
if (mUsesTexture2DProj)
{
out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
"{\n"
" return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, 0));\n"
"}\n"
"\n"
"float4 gl_texture2DProj(sampler2D s, float4 t)\n"
"{\n"
" return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, 0));\n"
"}\n"
"\n";
}
if (mUsesTexture2DProjLod)
{
out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n"
"{\n"
" return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, lod));\n"
"}\n"
"\n"
"float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n"
"{\n"
" return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, lod));\n"
"}\n"
"\n";
}
if (mUsesTextureCube)
{
out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
"{\n"
" return texCUBElod(s, float4(t.x, -t.y, t.z, 0));\n"
"}\n"
"\n";
}
if (mUsesTextureCubeLod)
{
out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n"
"{\n"
" return texCUBElod(s, float4(t.x, -t.y, t.z, lod));\n"
"}\n"
"\n";
}
}
if (mUsesFragCoord)
@ -1247,15 +1328,33 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
}
else if (name == "texture2DLod")
{
UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
if (node->getSequence().size() == 3)
{
mUsesTexture2DLod = true;
}
else UNREACHABLE();
out << "gl_texture2DLod(";
}
else if (name == "texture2DProjLod")
{
UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
if (node->getSequence().size() == 3)
{
mUsesTexture2DProjLod = true;
}
else UNREACHABLE();
out << "gl_texture2DProjLod(";
}
else if (name == "textureCubeLod")
{
UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
if (node->getSequence().size() == 3)
{
mUsesTextureCubeLod = true;
}
else UNREACHABLE();
out << "gl_textureCubeLod(";
}
else UNREACHABLE();
}
@ -1534,9 +1633,9 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
switch (node->getFlowOp())
{
case EOpKill: outputTriplet(visit, "discard", "", ""); break;
case EOpBreak: outputTriplet(visit, "break", "", ""); break;
case EOpContinue: outputTriplet(visit, "continue", "", ""); break;
case EOpKill: outputTriplet(visit, "discard;\n", "", ""); break;
case EOpBreak: outputTriplet(visit, "break;\n", "", ""); break;
case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
case EOpReturn:
if (visit == PreVisit)
{
@ -1706,7 +1805,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
if (comparator == EOpLessThan)
{
int iterations = (limit - initial + 1) / increment;
int iterations = (limit - initial) / increment;
if (iterations <= 255)
{
@ -1715,8 +1814,8 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
while (iterations > 0)
{
int remainder = (limit - initial + 1) % increment;
int clampedLimit = initial + increment * std::min(255, iterations) - 1 - remainder;
int remainder = (limit - initial) % increment;
int clampedLimit = initial + increment * std::min(255, iterations);
// for(int index = initial; index < clampedLimit; index += increment)

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -76,10 +76,13 @@ class OutputHLSL : public TIntermTraverser
// Parameters determining what goes in the header output
bool mUsesTexture2D;
bool mUsesTexture2D_bias;
bool mUsesTexture2DLod;
bool mUsesTexture2DProj;
bool mUsesTexture2DProj_bias;
bool mUsesTexture2DProjLod;
bool mUsesTextureCube;
bool mUsesTextureCube_bias;
bool mUsesTextureCubeLod;
bool mUsesDepthRange;
bool mUsesFragCoord;
bool mUsesPointCoord;

Просмотреть файл

@ -274,6 +274,8 @@ bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicTy
return true;
}
break;
default:
return false;
}
return false;
}
@ -558,7 +560,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
}
}
TIntermTyped* typed = node->getAsTyped();
TIntermTyped *typed = node ? node->getAsTyped() : 0;
if (typed == 0) {
error(line, "constructor argument does not have a type", "constructor", "");
return true;
@ -880,16 +882,17 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
//
// Returns true if there was an error.
//
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
{
if (reservedErrorCheck(line, identifier))
recover();
TVariable* variable = new TVariable(&identifier, TType(type));
variable = new TVariable(&identifier, TType(type));
if (! symbolTable.insert(*variable)) {
error(line, "redefinition", variable->getName().c_str(), "");
delete variable;
variable = 0;
return true;
}

Просмотреть файл

@ -81,7 +81,7 @@ struct TParseContext {
bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
bool containsSampler(TType& type);
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
bool extensionErrorCheck(int line, const TString&);
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);

Просмотреть файл

@ -151,16 +151,18 @@ const unsigned char TAllocation::userDataFill = 0xcd;
//
void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
{
#ifdef GUARD_BLOCKS
for (size_t x = 0; x < guardBlockSize; x++) {
if (blockMem[x] != val) {
char assertMsg[80];
// We don't print the assert message. It's here just to be helpful.
sprintf(assertMsg, "PoolAlloc: Damage %s %u byte allocation at 0x%p\n",
sprintf(assertMsg, "PoolAlloc: Damage %s %lu byte allocation at 0x%p\n",
locText, size, data());
assert(0 && "PoolAlloc: Damage in guard block");
}
}
#endif
}

Просмотреть файл

@ -57,6 +57,7 @@ public:
TInfoSink& getInfoSink() { return infoSink; }
const TVariableInfoList& getAttribs() const { return attribs; }
const TVariableInfoList& getUniforms() const { return uniforms; }
int getMappedNameMaxLength() const;
protected:
ShShaderType getShaderType() const { return shaderType; }
@ -70,6 +71,8 @@ protected:
bool validateLimitations(TIntermNode* root);
// Collect info for all attribs and uniforms.
void collectAttribsUniforms(TIntermNode* root);
// Map long variable names into shorter ones.
void mapLongVariableNames(TIntermNode* root);
// Translate to object code.
virtual void translate(TIntermNode* root) = 0;

Просмотреть файл

@ -37,7 +37,8 @@ static void getVariableInfo(ShShaderInfo varType,
int* length,
int* size,
ShDataType* type,
char* name)
char* name,
char* mappedName)
{
if (!handle || !size || !type || !name)
return;
@ -59,6 +60,8 @@ static void getVariableInfo(ShShaderInfo varType,
*size = varInfo.size;
*type = varInfo.type;
strcpy(name, varInfo.name.c_str());
if (mappedName)
strcpy(mappedName, varInfo.mappedName.c_str());
}
//
@ -194,7 +197,9 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
*params = getVariableMaxLength(compiler->getAttribs());
break;
case SH_MAPPED_NAME_MAX_LENGTH:
*params = compiler->getMappedNameMaxLength();
break;
default: UNREACHABLE();
}
}
@ -236,10 +241,11 @@ void ShGetActiveAttrib(const ShHandle handle,
int* length,
int* size,
ShDataType* type,
char* name)
char* name,
char* mappedName)
{
getVariableInfo(SH_ACTIVE_ATTRIBUTES,
handle, index, length, size, type, name);
handle, index, length, size, type, name, mappedName);
}
void ShGetActiveUniform(const ShHandle handle,
@ -247,8 +253,9 @@ void ShGetActiveUniform(const ShHandle handle,
int* length,
int* size,
ShDataType* type,
char* name)
char* name,
char* mappedName)
{
getVariableInfo(SH_ACTIVE_UNIFORMS,
handle, index, length, size, type, name);
handle, index, length, size, type, name, mappedName);
}

Просмотреть файл

@ -17,6 +17,17 @@ bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) {
return false;
}
void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) {
for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) {
if (i->index.id == symbol->getId()) {
ASSERT(i->loop != NULL);
i->loop->setUnrollFlag(true);
return;
}
}
UNREACHABLE();
}
// Traverses a node to check if it represents a constant index expression.
// Definition:
// constant-index-expressions are a superset of constant-expressions.
@ -54,6 +65,48 @@ private:
bool mValid;
const TLoopStack& mLoopStack;
};
// Traverses a node to check if it uses a loop index.
// If an int loop index is used in its body as a sampler array index,
// mark the loop for unroll.
class ValidateLoopIndexExpr : public TIntermTraverser {
public:
ValidateLoopIndexExpr(TLoopStack& stack)
: mUsesFloatLoopIndex(false),
mUsesIntLoopIndex(false),
mLoopStack(stack) {}
bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; }
bool usesIntLoopIndex() const { return mUsesIntLoopIndex; }
virtual void visitSymbol(TIntermSymbol* symbol) {
if (IsLoopIndex(symbol, mLoopStack)) {
switch (symbol->getBasicType()) {
case EbtFloat:
mUsesFloatLoopIndex = true;
break;
case EbtInt:
mUsesIntLoopIndex = true;
MarkLoopForUnroll(symbol, mLoopStack);
break;
default:
UNREACHABLE();
}
}
}
virtual void visitConstantUnion(TIntermConstantUnion*) {}
virtual bool visitBinary(Visit, TIntermBinary*) { return true; }
virtual bool visitUnary(Visit, TIntermUnary*) { return true; }
virtual bool visitSelection(Visit, TIntermSelection*) { return true; }
virtual bool visitAggregate(Visit, TIntermAggregate*) { return true; }
virtual bool visitLoop(Visit, TIntermLoop*) { return true; }
virtual bool visitBranch(Visit, TIntermBranch*) { return true; }
private:
bool mUsesFloatLoopIndex;
bool mUsesIntLoopIndex;
TLoopStack& mLoopStack;
};
} // namespace
ValidateLimitations::ValidateLimitations(ShShaderType shaderType,
@ -80,7 +133,28 @@ bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node)
// Check indexing.
switch (node->getOp()) {
case EOpIndexDirect:
validateIndexing(node);
break;
case EOpIndexIndirect:
#if defined(__APPLE__)
// Loop unrolling is a work-around for a Mac Cg compiler bug where it
// crashes when a sampler array's index is also the loop index.
// Once Apple fixes this bug, we should remove the code in this CL.
// See http://codereview.appspot.com/4331048/.
if ((node->getLeft() != NULL) && (node->getRight() != NULL) &&
(node->getLeft()->getAsSymbolNode())) {
TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode();
if (IsSampler(symbol->getBasicType()) && symbol->isArray()) {
ValidateLoopIndexExpr validate(mLoopStack);
node->getRight()->traverse(&validate);
if (validate.usesFloatLoopIndex()) {
error(node->getLine(),
"sampler array index is float loop index",
"for");
}
}
}
#endif
validateIndexing(node);
break;
default: break;
@ -120,6 +194,7 @@ bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node)
TLoopInfo info;
memset(&info, 0, sizeof(TLoopInfo));
info.loop = node;
if (!validateForLoopHeader(node, &info))
return false;

Просмотреть файл

@ -13,6 +13,7 @@ struct TLoopInfo {
struct TIndex {
int id; // symbol id.
} index;
TIntermLoop* loop;
};
typedef TVector<TLoopInfo> TLoopStack;

Просмотреть файл

@ -70,32 +70,37 @@ static ShDataType getVariableDataType(const TType& type)
static void getBuiltInVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList);
static void getUserDefinedVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList);
// Returns info for an attribute or uniform.
static void getVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList)
{
if (type.getBasicType() == EbtStruct) {
if (type.isArray()) {
for (int i = 0; i < type.getArraySize(); ++i) {
TString lname = name + arrayBrackets(i);
getUserDefinedVariableInfo(type, lname, infoList);
TString lmappedName = mappedName + arrayBrackets(i);
getUserDefinedVariableInfo(type, lname, lmappedName, infoList);
}
} else {
getUserDefinedVariableInfo(type, name, infoList);
getUserDefinedVariableInfo(type, name, mappedName, infoList);
}
} else {
getBuiltInVariableInfo(type, name, infoList);
getBuiltInVariableInfo(type, name, mappedName, infoList);
}
}
void getBuiltInVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList)
{
ASSERT(type.getBasicType() != EbtStruct);
@ -103,9 +108,11 @@ void getBuiltInVariableInfo(const TType& type,
TVariableInfo varInfo;
if (type.isArray()) {
varInfo.name = (name + "[0]").c_str();
varInfo.mappedName = (mappedName + "[0]").c_str();
varInfo.size = type.getArraySize();
} else {
varInfo.name = name.c_str();
varInfo.mappedName = mappedName.c_str();
varInfo.size = 1;
}
varInfo.type = getVariableDataType(type);
@ -114,16 +121,17 @@ void getBuiltInVariableInfo(const TType& type,
void getUserDefinedVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList)
{
ASSERT(type.getBasicType() == EbtStruct);
TString lname = name + ".";
const TTypeList* structure = type.getStruct();
for (size_t i = 0; i < structure->size(); ++i) {
const TType* fieldType = (*structure)[i].type;
getVariableInfo(*fieldType,
lname + fieldType->getFieldName(),
name + "." + fieldType->getFieldName(),
mappedName + "." + fieldType->getFieldName(),
infoList);
}
}
@ -186,7 +194,9 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
// cannot be initialized in a shader, we must have only
// TIntermSymbol nodes in the sequence.
ASSERT(variable != NULL);
getVariableInfo(variable->getType(), variable->getSymbol(),
getVariableInfo(variable->getType(),
variable->getOriginalSymbol(),
variable->getSymbol(),
infoList);
}
}

Просмотреть файл

@ -1,9 +1,12 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_VARIABLE_INFO_H_
#define COMPILER_VARIABLE_INFO_H_
#include "GLSLANG/ShaderLang.h"
#include "compiler/intermediate.h"
@ -11,6 +14,7 @@
// It is currently being used to store info about active attribs and uniforms.
struct TVariableInfo {
TPersistString name;
TPersistString mappedName;
ShDataType type;
int size;
};
@ -36,3 +40,4 @@ private:
TVariableInfoList& mUniforms;
};
#endif // COMPILER_VARIABLE_INFO_H_

Просмотреть файл

@ -1185,7 +1185,8 @@ init_declarator_list
}
}
| init_declarator_list COMMA IDENTIFIER {
$$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line), $3.line);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line);
$$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line);
if (context->structQualifierErrorCheck($3.line, $$.type))
context->recover();
@ -1193,8 +1194,11 @@ init_declarator_list
if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type))
context->recover();
if (context->nonInitErrorCheck($3.line, *$3.string, $$.type))
TVariable* variable = 0;
if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable))
context->recover();
if (symbol && variable)
symbol->setId(variable->getUniqueId());
}
| init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
if (context->structQualifierErrorCheck($3.line, $1.type))
@ -1230,12 +1234,12 @@ init_declarator_list
if (context->arraySizeErrorCheck($4.line, $5, size))
context->recover();
$1.type.setArray(true, size);
TVariable* variable;
TVariable* variable = 0;
if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
context->recover();
TType type = TType($1.type);
type.setArraySize(size);
$$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(0, *$3.string, type, $3.line), $3.line);
$$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line);
}
}
| init_declarator_list COMMA IDENTIFIER EQUAL initializer {
@ -1266,7 +1270,8 @@ single_declaration
$$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
}
| fully_specified_type IDENTIFIER {
$$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
$$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
if (context->structQualifierErrorCheck($2.line, $$.type))
context->recover();
@ -1276,11 +1281,15 @@ single_declaration
$$.type = $1;
if (context->nonInitErrorCheck($2.line, *$2.string, $$.type))
TVariable* variable = 0;
if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
| fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
$$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
$$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
if (context->structQualifierErrorCheck($2.line, $1))
context->recover();
@ -1294,9 +1303,11 @@ single_declaration
context->recover();
else {
$1.setArray(true);
TVariable* variable;
TVariable* variable = 0;
if (context->arrayErrorCheck($3.line, *$2.string, $1, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
}
| fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
@ -1305,7 +1316,8 @@ single_declaration
if (context->arraySizeErrorCheck($2.line, $4, size))
context->recover();
type.setArraySize(size);
$$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *$2.string, type, $2.line), $2.line);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line);
$$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
if (context->structQualifierErrorCheck($2.line, $1))
context->recover();
@ -1323,9 +1335,11 @@ single_declaration
context->recover();
$1.setArray(true, size);
TVariable* variable;
TVariable* variable = 0;
if (context->arrayErrorCheck($3.line, *$2.string, $1, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
}
| fully_specified_type IDENTIFIER EQUAL initializer {

Просмотреть файл

@ -325,7 +325,7 @@ typedef union YYSTYPE
};
} interm;
}
/* Line 187 of yacc.c. */
/* Line 193 of yacc.c. */
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@ -415,7 +415,7 @@ typedef short int yytype_int16;
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
# if YYENABLE_NLS
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@ -738,17 +738,17 @@ static const yytype_uint16 yyrline[] =
893, 910, 911, 924, 925, 926, 927, 928, 932, 935,
946, 954, 979, 984, 991, 1027, 1030, 1037, 1045, 1066,
1085, 1096, 1125, 1130, 1140, 1145, 1155, 1158, 1161, 1164,
1170, 1177, 1187, 1199, 1217, 1241, 1264, 1268, 1282, 1302,
1331, 1351, 1427, 1436, 1459, 1462, 1468, 1476, 1484, 1492,
1495, 1502, 1505, 1508, 1514, 1517, 1532, 1536, 1540, 1544,
1553, 1558, 1563, 1568, 1573, 1578, 1583, 1588, 1593, 1598,
1604, 1610, 1616, 1621, 1626, 1631, 1644, 1657, 1665, 1668,
1683, 1714, 1718, 1724, 1732, 1748, 1752, 1756, 1757, 1763,
1764, 1765, 1766, 1767, 1771, 1772, 1772, 1772, 1782, 1783,
1788, 1791, 1801, 1804, 1810, 1811, 1815, 1823, 1827, 1837,
1842, 1859, 1859, 1864, 1864, 1871, 1871, 1879, 1882, 1888,
1891, 1897, 1901, 1908, 1915, 1922, 1929, 1940, 1949, 1953,
1960, 1963, 1969, 1969
1170, 1177, 1187, 1203, 1221, 1245, 1268, 1272, 1290, 1313,
1345, 1365, 1441, 1450, 1473, 1476, 1482, 1490, 1498, 1506,
1509, 1516, 1519, 1522, 1528, 1531, 1546, 1550, 1554, 1558,
1567, 1572, 1577, 1582, 1587, 1592, 1597, 1602, 1607, 1612,
1618, 1624, 1630, 1635, 1640, 1645, 1658, 1671, 1679, 1682,
1697, 1728, 1732, 1738, 1746, 1762, 1766, 1770, 1771, 1777,
1778, 1779, 1780, 1781, 1785, 1786, 1786, 1786, 1796, 1797,
1802, 1805, 1815, 1818, 1824, 1825, 1829, 1837, 1841, 1851,
1856, 1873, 1873, 1878, 1878, 1885, 1885, 1893, 1896, 1902,
1905, 1911, 1915, 1922, 1929, 1936, 1943, 1954, 1963, 1967,
1974, 1977, 1983, 1983
};
#endif
@ -1361,7 +1361,7 @@ while (YYID (0))
we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
# if YYLTYPE_IS_TRIVIAL
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
@ -3373,7 +3373,8 @@ yyreduce:
case 92:
{
(yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yyvsp[(3) - (3)].lex).line), (yyvsp[(3) - (3)].lex).line);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yyvsp[(3) - (3)].lex).line);
(yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, symbol, (yyvsp[(3) - (3)].lex).line);
if (context->structQualifierErrorCheck((yyvsp[(3) - (3)].lex).line, (yyval.interm).type))
context->recover();
@ -3381,8 +3382,11 @@ yyreduce:
if (context->nonInitConstErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type))
context->recover();
if (context->nonInitErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type))
TVariable* variable = 0;
if (context->nonInitErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, variable))
context->recover();
if (symbol && variable)
symbol->setId(variable->getUniqueId());
;}
break;
@ -3426,12 +3430,12 @@ yyreduce:
if (context->arraySizeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(5) - (6)].interm.intermTypedNode), size))
context->recover();
(yyvsp[(1) - (6)].interm).type.setArray(true, size);
TVariable* variable;
TVariable* variable = 0;
if (context->arrayErrorCheck((yyvsp[(4) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, variable))
context->recover();
TType type = TType((yyvsp[(1) - (6)].interm).type);
type.setArraySize(size);
(yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(0, *(yyvsp[(3) - (6)].lex).string, type, (yyvsp[(3) - (6)].lex).line), (yyvsp[(3) - (6)].lex).line);
(yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *(yyvsp[(3) - (6)].lex).string, type, (yyvsp[(3) - (6)].lex).line), (yyvsp[(3) - (6)].lex).line);
}
;}
break;
@ -3471,7 +3475,8 @@ yyreduce:
case 97:
{
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line), (yyvsp[(2) - (2)].lex).line);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line);
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line);
if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type))
context->recover();
@ -3481,15 +3486,19 @@ yyreduce:
(yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type))
TVariable* variable = 0;
if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
;}
break;
case 98:
{
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line), (yyvsp[(2) - (4)].lex).line);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line);
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (4)].lex).line);
if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
context->recover();
@ -3503,9 +3512,11 @@ yyreduce:
context->recover();
else {
(yyvsp[(1) - (4)].interm.type).setArray(true);
TVariable* variable;
TVariable* variable = 0;
if (context->arrayErrorCheck((yyvsp[(3) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
;}
break;
@ -3518,7 +3529,8 @@ yyreduce:
if (context->arraySizeErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
context->recover();
type.setArraySize(size);
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line), (yyvsp[(2) - (5)].lex).line);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line);
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (5)].lex).line);
if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
context->recover();
@ -3536,9 +3548,11 @@ yyreduce:
context->recover();
(yyvsp[(1) - (5)].interm.type).setArray(true, size);
TVariable* variable;
TVariable* variable = 0;
if (context->arrayErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
;}
break;

Просмотреть файл

@ -262,7 +262,7 @@ typedef union YYSTYPE
};
} interm;
}
/* Line 1489 of yacc.c. */
/* Line 1529 of yacc.c. */
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

Просмотреть файл

@ -279,7 +279,8 @@ public:
init(aInit),
cond(aCond),
expr(aExpr),
body(aBody) { }
body(aBody),
unrollFlag(false) { }
virtual TIntermLoop* getAsLoopNode() { return this; }
virtual void traverse(TIntermTraverser*);
@ -290,12 +291,17 @@ public:
TIntermTyped* getExpression() { return expr; }
TIntermNode* getBody() { return body; }
void setUnrollFlag(bool flag) { unrollFlag = flag; }
bool getUnrollFlag() { return unrollFlag; }
protected:
TLoopType type;
TIntermNode* init; // for-loop initialization
TIntermTyped* cond; // loop exit condition
TIntermTyped* expr; // for-loop expression
TIntermNode* body; // loop body
bool unrollFlag; // Whether the loop should be unrolled or not.
};
//
@ -326,17 +332,23 @@ public:
// per process globalpoolallocator, then it causes increased memory usage per compile
// it is essential to use "symbol = sym" to assign to symbol
TIntermSymbol(int i, const TString& sym, const TType& t) :
TIntermTyped(t), id(i) { symbol = sym;}
TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; }
int getId() const { return id; }
const TString& getSymbol() const { return symbol; }
void setId(int newId) { id = newId; }
void setSymbol(const TString& sym) { symbol = sym; }
const TString& getOriginalSymbol() const { return originalSymbol; }
virtual void traverse(TIntermTraverser*);
virtual TIntermSymbol* getAsSymbolNode() { return this; }
protected:
int id;
TString symbol;
TString originalSymbol;
};
class TIntermConstantUnion : public TIntermTyped {

Просмотреть файл

@ -468,6 +468,17 @@ static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
val = *res;
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
token = eval(token, binop[i].prec, res, err, yylvalpp);
if (binop[i].op == op_div || binop[i].op == op_mod)
{
if (*res == 0)
{
CPPErrorToInfoLog("preprocessor divide or modulo by zero");
*err = 1;
return token;
}
}
*res = binop[i].op(val, *res);
}
return token;

Просмотреть файл

@ -373,7 +373,7 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} while (ch >= '0' && ch <= '9');
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
if (ch == '.' || ch == 'e' || ch == 'E') {
return lFloatConst(ch, len, yylvalpp);
} else {
assert(len <= MAX_SYMBOL_NAME_LEN);
@ -558,11 +558,9 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
return -1;
return '\n';
} else if (ch == '*') {
int nlcount = 0;
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
do {
while (ch != '*') {
if (ch == '\n') nlcount++;
if (ch == EOF) {
CPPErrorToInfoLog("EOF IN COMMENT");
return -1;
@ -575,9 +573,6 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
return -1;
}
} while (ch != '/');
if (nlcount) {
return '\n';
}
// Go try it again...
} else if (ch == '=') {
return CPP_DIV_ASSIGN;

Просмотреть файл

@ -49,7 +49,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define __SCANNER_H 1
// These lengths do not include the NULL terminator.
#define MAX_SYMBOL_NAME_LEN 127
#define MAX_SYMBOL_NAME_LEN 256
#define MAX_STRING_LEN 511
#include "compiler/preprocessor/parser.h"

Просмотреть файл

@ -64,6 +64,8 @@ void Config::setDefaults()
void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
{
mBindToTextureRGB = EGL_FALSE;
mBindToTextureRGBA = EGL_FALSE;
switch (renderTargetFormat)
{
case D3DFMT_A1R5G5B5:
@ -86,6 +88,7 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
mGreenSize = 8;
mBlueSize = 8;
mAlphaSize = 8;
mBindToTextureRGBA = true;
break;
case D3DFMT_R5G6B5:
mBufferSize = 16;
@ -100,6 +103,7 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
mGreenSize = 8;
mBlueSize = 8;
mAlphaSize = 0;
mBindToTextureRGB = true;
break;
default:
UNREACHABLE(); // Other formats should not be valid
@ -107,8 +111,6 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
mLuminanceSize = 0;
mAlphaMaskSize = 0;
mBindToTextureRGB = EGL_FALSE;
mBindToTextureRGBA = EGL_FALSE;
mColorBufferType = EGL_RGB_BUFFER;
mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
mConfigID = 0;
@ -116,6 +118,10 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
switch (depthStencilFormat)
{
case D3DFMT_UNKNOWN:
mDepthSize = 0;
mStencilSize = 0;
break;
// case D3DFMT_D16_LOCKABLE:
// mDepthSize = 16;
// mStencilSize = 0;

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -14,6 +14,7 @@
#include <vector>
#include "common/debug.h"
#include "libGLESv2/mathutil.h"
#include "libEGL/main.h"
@ -27,8 +28,9 @@ Display::Display(HDC deviceContext) : mDc(deviceContext)
mD3d9Module = NULL;
mD3d9 = NULL;
mD3d9ex = NULL;
mD3d9Ex = NULL;
mDevice = NULL;
mDeviceEx = NULL;
mDeviceWindow = NULL;
mAdapter = D3DADAPTER_DEFAULT;
@ -68,10 +70,10 @@ bool Display::initialize()
// Use Direct3D9Ex if available. Among other things, this version is less
// inclined to report a lost context, for example when the user switches
// desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
if (ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
if (ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
{
ASSERT(mD3d9ex);
mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
ASSERT(mD3d9Ex);
mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
ASSERT(mD3d9);
}
else
@ -143,6 +145,7 @@ bool Display::initialize()
const D3DFORMAT depthStencilFormats[] =
{
D3DFMT_UNKNOWN,
// D3DFMT_D16_LOCKABLE,
D3DFMT_D32,
// D3DFMT_D15S1,
@ -170,11 +173,19 @@ bool Display::initialize()
for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
{
D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
HRESULT result = D3D_OK;
if(depthStencilFormat != D3DFMT_UNKNOWN)
{
result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
}
if (SUCCEEDED(result))
{
HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
if(depthStencilFormat != D3DFMT_UNKNOWN)
{
result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
}
if (SUCCEEDED(result))
{
@ -207,6 +218,8 @@ bool Display::initialize()
return false;
}
initExtensionString();
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
static const TCHAR className[] = TEXT("STATIC");
@ -230,7 +243,7 @@ void Display::terminate()
if (mDevice)
{
// If the device is lost, reset it first to prevent leaving the driver in an unstable state
if (FAILED(mDevice->TestCooperativeLevel()))
if (isDeviceLost())
{
resetDevice();
}
@ -239,6 +252,12 @@ void Display::terminate()
mDevice = NULL;
}
if (mDeviceEx)
{
mDeviceEx->Release();
mDeviceEx = NULL;
}
if (mD3d9)
{
mD3d9->Release();
@ -251,10 +270,10 @@ void Display::terminate()
mDeviceWindow = NULL;
}
if (mD3d9ex)
if (mD3d9Ex)
{
mD3d9ex->Release();
mD3d9ex = NULL;
mD3d9Ex->Release();
mD3d9Ex = NULL;
}
if (mD3d9Module)
@ -356,6 +375,12 @@ bool Display::createDevice()
}
}
if (mD3d9Ex)
{
result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
ASSERT(SUCCEEDED(result));
}
// Permanent non-default states
mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
@ -387,24 +412,162 @@ bool Display::resetDevice()
return true;
}
Surface *Display::createWindowSurface(HWND window, EGLConfig config)
EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
{
const Config *configuration = mConfigSet.get(config);
Surface *surface = new Surface(this, configuration, window);
mSurfaceSet.insert(surface);
return surface;
if (attribList)
{
while (*attribList != EGL_NONE)
{
switch (attribList[0])
{
case EGL_RENDER_BUFFER:
switch (attribList[1])
{
case EGL_BACK_BUFFER:
break;
case EGL_SINGLE_BUFFER:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
break;
case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
case EGL_VG_ALPHA_FORMAT:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
Surface *Display::createOffscreenSurface(int width, int height, EGLConfig config)
{
const Config *configuration = mConfigSet.get(config);
attribList += 2;
}
}
if (hasExistingWindowSurface(window))
{
return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
Surface *surface = new Surface(this, configuration, window);
if (!surface->initialize())
{
delete surface;
return EGL_NO_SURFACE;
}
Surface *surface = new Surface(this, configuration, width, height);
mSurfaceSet.insert(surface);
return surface;
return success(surface);
}
EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
{
EGLint width = 0, height = 0;
EGLenum textureFormat = EGL_NO_TEXTURE;
EGLenum textureTarget = EGL_NO_TEXTURE;
const Config *configuration = mConfigSet.get(config);
if (attribList)
{
while (*attribList != EGL_NONE)
{
switch (attribList[0])
{
case EGL_WIDTH:
width = attribList[1];
break;
case EGL_HEIGHT:
height = attribList[1];
break;
case EGL_LARGEST_PBUFFER:
if (attribList[1] != EGL_FALSE)
UNIMPLEMENTED(); // FIXME
break;
case EGL_TEXTURE_FORMAT:
switch (attribList[1])
{
case EGL_NO_TEXTURE:
case EGL_TEXTURE_RGB:
case EGL_TEXTURE_RGBA:
textureFormat = attribList[1];
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
break;
case EGL_TEXTURE_TARGET:
switch (attribList[1])
{
case EGL_NO_TEXTURE:
case EGL_TEXTURE_2D:
textureTarget = attribList[1];
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
break;
case EGL_MIPMAP_TEXTURE:
if (attribList[1] != EGL_FALSE)
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
break;
case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
case EGL_VG_ALPHA_FORMAT:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
attribList += 2;
}
}
if (width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
}
if (width == 0 || height == 0)
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
if (textureFormat != EGL_NO_TEXTURE && !getNonPow2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height)))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
(textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
(textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
if (!surface->initialize())
{
delete surface;
return EGL_NO_SURFACE;
}
mSurfaceSet.insert(surface);
return success(surface);
}
EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
@ -416,7 +579,7 @@ EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *sha
return NULL;
}
}
else if (FAILED(mDevice->TestCooperativeLevel())) // Lost device
else if (isDeviceLost()) // Lost device
{
if (!resetDevice())
{
@ -439,17 +602,24 @@ EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *sha
}
void Display::destroySurface(egl::Surface *surface)
{
if (surface == egl::getCurrentDrawSurface() || surface == egl::getCurrentReadSurface())
{
surface->setPendingDestroy();
}
else
{
delete surface;
mSurfaceSet.erase(surface);
}
}
void Display::destroyContext(gl::Context *context)
{
glDestroyContext(context);
mContextSet.erase(context);
if (mContextSet.empty() && mDevice && FAILED(mDevice->TestCooperativeLevel())) // Last context of a lost device
if (mContextSet.empty() && mDevice && isDeviceLost()) // Last context of a lost device
{
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
{
@ -458,7 +628,7 @@ void Display::destroyContext(gl::Context *context)
}
}
bool Display::isInitialized()
bool Display::isInitialized() const
{
return mD3d9 != NULL && mConfigSet.size() > 0;
}
@ -475,7 +645,7 @@ bool Display::isValidContext(gl::Context *context)
bool Display::isValidSurface(egl::Surface *surface)
{
return mSurfaceSet.find(surface) != mSurfaceSet.end();
return mSurfaceSet.find(surface) != mSurfaceSet.end() && !surface->isPendingDestroy();
}
bool Display::hasExistingWindowSurface(HWND window)
@ -519,6 +689,18 @@ D3DCAPS9 Display::getDeviceCaps()
return mDeviceCaps;
}
bool Display::isDeviceLost()
{
if (mDeviceEx)
{
return FAILED(mDeviceEx->CheckDeviceState(NULL));
}
else
{
return FAILED(mDevice->TestCooperativeLevel());
}
}
void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
{
for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
@ -610,9 +792,14 @@ bool Display::getLuminanceAlphaTextureSupport()
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
}
bool Display::getNonPow2TextureSupport()
{
return !(mDeviceCaps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL));
}
D3DPOOL Display::getBufferPool(DWORD usage) const
{
if (mD3d9ex != NULL)
if (mD3d9Ex != NULL)
{
return D3DPOOL_DEFAULT;
}
@ -660,4 +847,43 @@ D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
return presentParameters;
}
void Display::initExtensionString()
{
mExtensionString += "EGL_ANGLE_query_surface_pointer ";
if (isD3d9ExDevice()) {
mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle ";
mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
}
std::string::size_type end = mExtensionString.find_last_not_of(' ');
if (end != std::string::npos)
{
mExtensionString.resize(end+1);
}
}
const char *Display::getExtensionString() const
{
return mExtensionString.c_str();
}
// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
// We test this using D3D9 by checking support for the R16F format.
bool Display::getVertexTextureSupport() const
{
if (!isInitialized() || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
{
return false;
}
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
return SUCCEEDED(result);
}
}

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -42,14 +42,14 @@ class Display
bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
egl::Surface *createWindowSurface(HWND window, EGLConfig config);
egl::Surface *createOffscreenSurface(int width, int height, EGLConfig config);
EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList);
EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);
void destroySurface(egl::Surface *surface);
void destroyContext(gl::Context *context);
bool isInitialized();
bool isInitialized() const;
bool isValidConfig(EGLConfig config);
bool isValidContext(gl::Context *context);
bool isValidSurface(egl::Surface *surface);
@ -60,6 +60,7 @@ class Display
virtual IDirect3DDevice9 *getDevice();
virtual D3DCAPS9 getDeviceCaps();
bool isDeviceLost();
virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
virtual bool getCompressedTextureSupport();
virtual bool getEventQuerySupport();
@ -67,9 +68,12 @@ class Display
virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable);
virtual bool getLuminanceTextureSupport();
virtual bool getLuminanceAlphaTextureSupport();
virtual bool getNonPow2TextureSupport();
virtual bool getVertexTextureSupport() const;
virtual D3DPOOL getBufferPool(DWORD usage) const;
bool isD3d9exDevice() { return mD3d9ex != NULL; }
bool isD3d9ExDevice() { return mD3d9Ex != NULL; }
const char *getExtensionString() const;
private:
DISALLOW_COPY_AND_ASSIGN(Display);
@ -83,8 +87,9 @@ class Display
UINT mAdapter;
D3DDEVTYPE mDeviceType;
IDirect3D9 *mD3d9; // Always valid after successful initialization.
IDirect3D9Ex *mD3d9ex; // Might be null if D3D9Ex is not supported.
IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported.
IDirect3DDevice9 *mDevice;
IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported.
D3DCAPS9 mDeviceCaps;
HWND mDeviceWindow;
@ -102,6 +107,9 @@ class Display
bool createDevice();
bool resetDevice();
void initExtensionString();
std::string mExtensionString;
};
}

Просмотреть файл

@ -91,6 +91,8 @@ CPPSRCS = \
ossource_win.cpp \
util.cpp \
ValidateLimitations.cpp \
ForLoopUnroll.cpp \
MapLongVariableNames.cpp \
$(NULL)
# flex/yacc generated files

Просмотреть файл

@ -13,6 +13,7 @@
#include "libEGL/Surface.h"
#include "common/debug.h"
#include "libGLESv2/Texture.h"
#include "libEGL/main.h"
#include "libEGL/Display.h"
@ -27,6 +28,9 @@ Surface::Surface(Display *display, const Config *config, HWND window)
mRenderTarget = NULL;
mOffscreenTexture = NULL;
mShareHandle = NULL;
mTexture = NULL;
mTextureFormat = EGL_NO_TEXTURE;
mTextureTarget = EGL_NO_TEXTURE;
mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
mRenderBuffer = EGL_BACK_BUFFER;
@ -34,19 +38,22 @@ Surface::Surface(Display *display, const Config *config, HWND window)
mSwapInterval = -1;
setSwapInterval(1);
mIsPendingDestroy = false;
subclassWindow();
resetSwapChain();
}
Surface::Surface(Display *display, const Config *config, EGLint width, EGLint height)
: mDisplay(display), mWindow(NULL), mConfig(config), mWidth(width), mHeight(height)
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)
{
mSwapChain = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
mOffscreenTexture = NULL;
mShareHandle = NULL;
mWindowSubclassed = false;
mTexture = NULL;
mTextureFormat = textureFormat;
mTextureTarget = textureType;
mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
mRenderBuffer = EGL_BACK_BUFFER;
@ -54,7 +61,7 @@ Surface::Surface(Display *display, const Config *config, EGLint width, EGLint he
mSwapInterval = -1;
setSwapInterval(1);
resetSwapChain(width, height);
mIsPendingDestroy = false;
}
Surface::~Surface()
@ -63,6 +70,12 @@ Surface::~Surface()
release();
}
bool Surface::initialize()
{
ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil);
return resetSwapChain();
}
void Surface::release()
{
if (mSwapChain)
@ -88,13 +101,19 @@ void Surface::release()
mOffscreenTexture->Release();
mOffscreenTexture = NULL;
}
if (mTexture)
{
mTexture->releaseTexImage();
mTexture = NULL;
}
}
void Surface::resetSwapChain()
bool Surface::resetSwapChain()
{
if (!mWindow) {
resetSwapChain(mWidth, mHeight);
return;
if (!mWindow)
{
return resetSwapChain(mWidth, mHeight);
}
RECT windowRect;
@ -103,19 +122,19 @@ void Surface::resetSwapChain()
ASSERT(false);
ERR("Could not retrieve the window dimensions");
return;
return false;
}
resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
}
void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
IDirect3DDevice9 *device = mDisplay->getDevice();
if (device == NULL)
{
return;
return false;
}
// Evict all non-render target textures to system memory and release all resources
@ -145,7 +164,7 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
} else {
HANDLE *pShareHandle = NULL;
if (mDisplay->isD3d9exDevice()) {
if (mDisplay->isD3d9ExDevice()) {
pShareHandle = &mShareHandle;
}
@ -159,12 +178,15 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
release();
return error(EGL_BAD_ALLOC);
return error(EGL_BAD_ALLOC, false);
}
if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
{
result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL);
}
if (FAILED(result))
{
@ -172,7 +194,7 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
release();
return error(EGL_BAD_ALLOC);
return error(EGL_BAD_ALLOC, false);
}
if (mWindow) {
@ -186,6 +208,7 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
mHeight = presentParameters.BackBufferHeight;
mPresentIntervalDirty = false;
return true;
}
HWND Surface::getWindowHandle()
@ -347,6 +370,16 @@ IDirect3DSurface9 *Surface::getDepthStencil()
return mDepthStencil;
}
IDirect3DTexture9 *Surface::getOffscreenTexture()
{
if (mOffscreenTexture)
{
mOffscreenTexture->AddRef();
}
return mOffscreenTexture;
}
void Surface::setSwapInterval(EGLint interval)
{
if (mSwapInterval == interval)
@ -361,4 +394,38 @@ void Surface::setSwapInterval(EGLint interval)
mPresentInterval = convertInterval(mSwapInterval);
mPresentIntervalDirty = true;
}
EGLenum Surface::getTextureFormat() const
{
return mTextureFormat;
}
EGLenum Surface::getTextureTarget() const
{
return mTextureTarget;
}
void Surface::setBoundTexture(gl::Texture2D *texture)
{
mTexture = texture;
}
gl::Texture2D *Surface::getBoundTexture() const
{
return mTexture;
}
D3DFORMAT Surface::getFormat() const
{
return mConfig->mRenderTargetFormat;
}
void Surface::setPendingDestroy() {
mIsPendingDestroy = true;
}
bool Surface::isPendingDestroy() const {
return mIsPendingDestroy;
}
}

Просмотреть файл

@ -17,6 +17,11 @@
#include "common/angleutils.h"
namespace gl
{
class Texture2D;
}
namespace egl
{
class Display;
@ -26,12 +31,13 @@ class Surface
{
public:
Surface(Display *display, const egl::Config *config, HWND window);
Surface(Display *display, const egl::Config *config, EGLint width, EGLint height);
Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
~Surface();
bool initialize();
void release();
void resetSwapChain();
bool resetSwapChain();
HWND getWindowHandle();
bool swap();
@ -41,12 +47,23 @@ class Surface
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture();
HANDLE getShareHandle() { return mShareHandle; }
void setSwapInterval(EGLint interval);
bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
virtual EGLenum getTextureFormat() const;
virtual EGLenum getTextureTarget() const;
virtual D3DFORMAT getFormat() const;
virtual void setBoundTexture(gl::Texture2D *texture);
virtual gl::Texture2D *getBoundTexture() const;
void setPendingDestroy();
bool isPendingDestroy() const;
private:
DISALLOW_COPY_AND_ASSIGN(Surface);
@ -57,10 +74,11 @@ private:
IDirect3DTexture9* mOffscreenTexture;
HANDLE mShareHandle;
bool mIsPendingDestroy;
void subclassWindow();
void unsubclassWindow();
void resetSwapChain(int backbufferWidth, int backbufferHeight);
bool resetSwapChain(int backbufferWidth, int backbufferHeight);
static DWORD convertInterval(EGLint interval);
const HWND mWindow; // Window that the surface is created for.
@ -77,13 +95,14 @@ private:
EGLint mPixelAspectRatio; // Display aspect ratio
EGLenum mRenderBuffer; // Render buffer
EGLenum mSwapBehavior; // Buffer swap behavior
// EGLenum textureFormat; // Format of texture: RGB, RGBA, or no texture
// EGLenum textureTarget; // Type of texture: 2D or no texture
EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture
EGLenum mTextureTarget; // Type of texture: 2D or no texture
// EGLenum vgAlphaFormat; // Alpha format for OpenVG
// EGLenum vgColorSpace; // Color space for OpenVG
EGLint mSwapInterval;
DWORD mPresentInterval;
bool mPresentIntervalDirty;
gl::Texture2D *mTexture;
};
}

Просмотреть файл

@ -11,12 +11,13 @@
#include "common/debug.h"
#include "common/version.h"
#include "libGLESv2/Context.h"
#include "libGLESv2/Texture.h"
#include "libEGL/main.h"
#include "libEGL/Display.h"
bool validate(egl::Display *display)
bool validateDisplay(egl::Display *display)
{
if (display == EGL_NO_DISPLAY)
{
@ -31,9 +32,9 @@ bool validate(egl::Display *display)
return true;
}
bool validate(egl::Display *display, EGLConfig config)
bool validateConfig(egl::Display *display, EGLConfig config)
{
if (!validate(display))
if (!validateDisplay(display))
{
return false;
}
@ -46,9 +47,9 @@ bool validate(egl::Display *display, EGLConfig config)
return true;
}
bool validate(egl::Display *display, gl::Context *context)
bool validateContext(egl::Display *display, gl::Context *context)
{
if (!validate(display))
if (!validateDisplay(display))
{
return false;
}
@ -61,9 +62,9 @@ bool validate(egl::Display *display, gl::Context *context)
return true;
}
bool validate(egl::Display *display, egl::Surface *surface)
bool validateSurface(egl::Display *display, egl::Surface *surface)
{
if (!validate(display))
if (!validateDisplay(display))
{
return false;
}
@ -184,7 +185,7 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display))
if (!validateDisplay(display))
{
return NULL;
}
@ -194,7 +195,7 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
case EGL_CLIENT_APIS:
return success("OpenGL_ES");
case EGL_EXTENSIONS:
return success("EGL_ANGLE_query_surface_pointer EGL_ANGLE_surface_d3d_share_handle");
return display->getExtensionString();
case EGL_VENDOR:
return success("Google Inc.");
case EGL_VERSION:
@ -221,7 +222,7 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display))
if (!validateDisplay(display))
{
return EGL_FALSE;
}
@ -258,7 +259,7 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display))
if (!validateDisplay(display))
{
return EGL_FALSE;
}
@ -296,7 +297,7 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display, config))
if (!validateConfig(display, config))
{
return EGL_FALSE;
}
@ -325,7 +326,7 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display, config))
if (!validateConfig(display, config))
{
return EGL_NO_SURFACE;
}
@ -337,43 +338,7 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG
return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
if (attrib_list)
{
while (*attrib_list != EGL_NONE)
{
switch (attrib_list[0])
{
case EGL_RENDER_BUFFER:
switch (attrib_list[1])
{
case EGL_BACK_BUFFER:
break;
case EGL_SINGLE_BUFFER:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
break;
case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
case EGL_VG_ALPHA_FORMAT:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
attrib_list += 2;
}
}
if (display->hasExistingWindowSurface(window))
{
return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
EGLSurface surface = (EGLSurface)display->createWindowSurface(window, config);
return success(surface);
return display->createWindowSurface(window, config, attrib_list);
}
catch(std::bad_alloc&)
{
@ -391,61 +356,13 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
EGLint width = 0, height = 0;
if (!validate(display, config))
if (!validateConfig(display, config))
{
return EGL_NO_SURFACE;
}
if (attrib_list)
{
while (*attrib_list != EGL_NONE)
{
switch (attrib_list[0])
{
case EGL_WIDTH:
width = attrib_list[1];
break;
case EGL_HEIGHT:
height = attrib_list[1];
break;
case EGL_LARGEST_PBUFFER:
if (attrib_list[1] != EGL_FALSE)
UNIMPLEMENTED(); // FIXME
break;
case EGL_TEXTURE_FORMAT:
case EGL_TEXTURE_TARGET:
switch (attrib_list[1])
{
case EGL_NO_TEXTURE:
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
break;
case EGL_MIPMAP_TEXTURE:
if (attrib_list[1] != EGL_FALSE)
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
break;
case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
case EGL_VG_ALPHA_FORMAT:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
attrib_list += 2;
}
}
if (width == 0 || height == 0)
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
EGLSurface surface = (EGLSurface)display->createOffscreenSurface(width, height, config);
return success(surface);
return display->createOffscreenSurface(config, NULL, attrib_list);
}
catch(std::bad_alloc&)
{
@ -464,7 +381,7 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display, config))
if (!validateConfig(display, config))
{
return EGL_NO_SURFACE;
}
@ -488,8 +405,9 @@ EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
if (!validate(display))
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
@ -519,8 +437,9 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = (egl::Surface*)surface;
if (!validate(display))
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
@ -530,8 +449,6 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
egl::Surface *eglSurface = (egl::Surface*)surface;
switch (attribute)
{
case EGL_VG_ALPHA_FORMAT:
@ -604,8 +521,9 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = (egl::Surface*)surface;
if (!validate(display))
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
@ -615,11 +533,9 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
egl::Surface *eglSurface = (egl::Surface*)surface;
switch (attribute)
{
case EGL_D3D_TEXTURE_SHARE_HANDLE_ANGLE:
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
*value = (void*) eglSurface->getShareHandle();
break;
default:
@ -729,14 +645,17 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display, config))
if (!validateConfig(display, config))
{
return EGL_NO_SURFACE;
}
UNIMPLEMENTED(); // FIXME
if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
{
return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
}
return success(EGL_NO_SURFACE);
return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
}
catch(std::bad_alloc&)
{
@ -754,8 +673,9 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
if (!validate(display))
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
@ -779,15 +699,36 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
if (!validate(display))
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
// FIXME - need implementation
if (buffer != EGL_BACK_BUFFER)
{
return error(EGL_BAD_PARAMETER, EGL_FALSE);
}
return success(EGL_FALSE);
if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
{
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
if (eglSurface->getBoundTexture())
{
return error(EGL_BAD_ACCESS, EGL_FALSE);
}
if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
return error(EGL_BAD_MATCH, EGL_FALSE);
}
glBindTexImage(eglSurface);
return success(EGL_TRUE);
}
catch(std::bad_alloc&)
{
@ -804,15 +745,36 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
if (!validate(display))
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
// FIXME - need implementation
if (buffer != EGL_BACK_BUFFER)
{
return error(EGL_BAD_PARAMETER, EGL_FALSE);
}
return success(EGL_FALSE);
if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
{
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
return error(EGL_BAD_MATCH, EGL_FALSE);
}
gl::Texture2D *texture = eglSurface->getBoundTexture();
if (texture)
{
texture->releaseTexImage();
}
return success(EGL_TRUE);
}
catch(std::bad_alloc&)
{
@ -830,7 +792,7 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display))
if (!validateDisplay(display))
{
return EGL_FALSE;
}
@ -885,7 +847,7 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display, config))
if (!validateConfig(display, config))
{
return EGL_NO_CONTEXT;
}
@ -909,8 +871,9 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
gl::Context *context = static_cast<gl::Context*>(ctx);
if (!validate(display))
if (!validateContext(display, context))
{
return EGL_FALSE;
}
@ -920,7 +883,7 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
return error(EGL_BAD_CONTEXT, EGL_FALSE);
}
display->destroyContext((gl::Context*)ctx);
display->destroyContext(context);
return success(EGL_TRUE);
}
@ -943,18 +906,18 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
gl::Context *context = static_cast<gl::Context*>(ctx);
IDirect3DDevice9 *device = display->getDevice();
if (!device || FAILED(device->TestCooperativeLevel()))
if (!device || display->isDeviceLost())
{
return error(EGL_CONTEXT_LOST, EGL_FALSE);
}
if (ctx != EGL_NO_CONTEXT && !validate(display, context))
if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
{
return EGL_FALSE;
}
if ((draw != EGL_NO_SURFACE && !validate(display, static_cast<egl::Surface*>(draw))) ||
(read != EGL_NO_SURFACE && !validate(display, static_cast<egl::Surface*>(read))))
if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
(read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
{
return EGL_FALSE;
}
@ -964,12 +927,27 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
UNIMPLEMENTED(); // FIXME
}
egl::Surface* previousDraw = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
egl::Surface* previousRead = static_cast<egl::Surface*>(egl::getCurrentReadSurface());
egl::setCurrentDisplay(dpy);
egl::setCurrentDrawSurface(draw);
egl::setCurrentReadSurface(read);
glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
// If the previous surfaces are still current, this might just flag
// them as pending destruction again, deferring destruction to a future
// eglMakeCurrent or eglTerminate call.
if (previousDraw && previousDraw->isPendingDestroy())
{
eglDestroySurface(dpy, previousDraw);
}
if (previousRead && previousRead != previousDraw && previousRead->isPendingDestroy())
{
eglDestroySurface(dpy, previousRead);
}
return success(EGL_TRUE);
}
catch(std::bad_alloc&)
@ -1053,8 +1031,9 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
gl::Context *context = static_cast<gl::Context*>(ctx);
if (!validate(display))
if (!validateContext(display, context))
{
return EGL_FALSE;
}
@ -1114,8 +1093,9 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = (egl::Surface*)surface;
if (!validate(display))
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
@ -1125,8 +1105,6 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
egl::Surface *eglSurface = (egl::Surface*)surface;
if (eglSurface->swap())
{
return success(EGL_TRUE);
@ -1147,8 +1125,9 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
if (!validate(display))
if (!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}

Просмотреть файл

@ -155,16 +155,23 @@ void Blit::initGeometry()
IDirect3DDevice9 *device = getDevice();
HRESULT hr = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
if (FAILED(hr))
if (FAILED(result))
{
ASSERT(hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return error(GL_OUT_OF_MEMORY);
}
void *lockPtr = NULL;
result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
if (FAILED(result) || lockPtr == NULL)
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return error(GL_OUT_OF_MEMORY);
}
void *lockPtr;
mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
memcpy(lockPtr, quad, sizeof(quad));
mQuadVertexBuffer->Unlock();
@ -174,10 +181,11 @@ void Blit::initGeometry()
D3DDECL_END()
};
hr = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
if (FAILED(hr))
result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
if (FAILED(result))
{
ASSERT(hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return error(GL_OUT_OF_MEMORY);
}
}
@ -287,6 +295,34 @@ bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
return true;
}
bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
{
IDirect3DDevice9 *device = getDevice();
D3DSURFACE_DESC sourceDesc;
D3DSURFACE_DESC destDesc;
source->GetDesc(&sourceDesc);
dest->GetDesc(&destDesc);
if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET) // Can use StretchRect
{
RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return error(GL_OUT_OF_MEMORY, false);
}
}
else
{
return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
}
return true;
}
bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
{
IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);

Просмотреть файл

@ -28,6 +28,10 @@ class Blit
explicit Blit(Context *context);
~Blit();
// Copy from source surface to dest surface.
// sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
// Copy from source surface to dest surface.
// sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
// source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.

Просмотреть файл

@ -11,8 +11,8 @@
#include "libGLESv2/Buffer.h"
#include "libGLESv2/main.h"
#include "libGLESv2/geometry/VertexDataManager.h"
#include "libGLESv2/geometry/IndexDataManager.h"
#include "libGLESv2/VertexDataManager.h"
#include "libGLESv2/IndexDataManager.h"
namespace gl
{
@ -23,15 +23,16 @@ Buffer::Buffer(GLuint id) : RefCountObject(id)
mSize = 0;
mUsage = GL_DYNAMIC_DRAW;
mVertexBuffer = NULL;
mIndexBuffer = NULL;
mStaticVertexBuffer = NULL;
mStaticIndexBuffer = NULL;
mUnmodifiedDataUse = 0;
}
Buffer::~Buffer()
{
delete[] mContents;
delete mVertexBuffer;
delete mIndexBuffer;
delete mStaticVertexBuffer;
delete mStaticIndexBuffer;
}
void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
@ -60,8 +61,8 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
if (usage == GL_STATIC_DRAW)
{
mVertexBuffer = new StaticVertexBuffer(getDevice());
mIndexBuffer = new StaticIndexBuffer(getDevice());
mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
}
}
@ -69,38 +70,46 @@ void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
memcpy(mContents + offset, data, size);
if ((mVertexBuffer && mVertexBuffer->size() != 0) || (mIndexBuffer && mIndexBuffer->size() != 0))
if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0))
{
invalidateStaticData();
if (mUsage == GL_STATIC_DRAW)
{
// If applications update the buffer data after it has already been used in a draw call,
// it most likely isn't used as a static buffer so we should fall back to streaming usage
// for best performance. So ignore the usage hint and don't create new static buffers.
// mVertexBuffer = new StaticVertexBuffer(getDevice());
// mIndexBuffer = new StaticIndexBuffer(getDevice());
}
}
}
StaticVertexBuffer *Buffer::getVertexBuffer()
StaticVertexBuffer *Buffer::getStaticVertexBuffer()
{
return mVertexBuffer;
return mStaticVertexBuffer;
}
StaticIndexBuffer *Buffer::getIndexBuffer()
StaticIndexBuffer *Buffer::getStaticIndexBuffer()
{
return mIndexBuffer;
return mStaticIndexBuffer;
}
void Buffer::invalidateStaticData()
{
delete mVertexBuffer;
mVertexBuffer = NULL;
delete mStaticVertexBuffer;
mStaticVertexBuffer = NULL;
delete mIndexBuffer;
mIndexBuffer = NULL;
delete mStaticIndexBuffer;
mStaticIndexBuffer = NULL;
mUnmodifiedDataUse = 0;
}
// Creates static buffers if sufficient used data has been left unmodified
void Buffer::promoteStaticUsage(int dataSize)
{
if (!mStaticVertexBuffer && !mStaticIndexBuffer)
{
mUnmodifiedDataUse += dataSize;
if (mUnmodifiedDataUse > 3 * mSize)
{
mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
}
}
}
}

Просмотреть файл

@ -39,9 +39,10 @@ class Buffer : public RefCountObject
size_t size() const { return mSize; }
GLenum usage() const { return mUsage; }
StaticVertexBuffer *getVertexBuffer();
StaticIndexBuffer *getIndexBuffer();
StaticVertexBuffer *getStaticVertexBuffer();
StaticIndexBuffer *getStaticIndexBuffer();
void invalidateStaticData();
void promoteStaticUsage(int dataSize);
private:
DISALLOW_COPY_AND_ASSIGN(Buffer);
@ -50,8 +51,9 @@ class Buffer : public RefCountObject
size_t mSize;
GLenum mUsage;
StaticVertexBuffer *mVertexBuffer;
StaticIndexBuffer *mIndexBuffer;
StaticVertexBuffer *mStaticVertexBuffer;
StaticIndexBuffer *mStaticIndexBuffer;
size_t mUnmodifiedDataUse;
};
}

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -25,17 +25,23 @@
#include "libGLESv2/RenderBuffer.h"
#include "libGLESv2/Shader.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/geometry/VertexDataManager.h"
#include "libGLESv2/geometry/IndexDataManager.h"
#include "libGLESv2/VertexDataManager.h"
#include "libGLESv2/IndexDataManager.h"
#undef near
#undef far
namespace
{
enum { CLOSING_INDEX_BUFFER_SIZE = 4096 };
}
namespace gl
{
Context::Context(const egl::Config *config, const gl::Context *shareContext)
: mConfig(config)
Context::Context(const egl::Config *config, const gl::Context *shareContext) : mConfig(config)
{
mFenceHandleAllocator.setBaseHandle(0);
setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mState.depthClearValue = 1.0f;
@ -140,6 +146,7 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext)
mVertexDataManager = NULL;
mIndexDataManager = NULL;
mBlit = NULL;
mClosingIB = NULL;
mInvalidEnum = false;
mInvalidValue = false;
@ -184,15 +191,15 @@ Context::~Context()
mMultiSampleSupport.erase(mMultiSampleSupport.begin());
}
for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
{
for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
{
mState.samplerTexture[type][sampler].set(NULL);
}
}
for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
{
mIncompleteTextures[type].set(NULL);
}
@ -212,6 +219,7 @@ Context::~Context()
delete mVertexDataManager;
delete mIndexDataManager;
delete mBlit;
delete mClosingIB;
if (mMaskedClearSavedState)
{
@ -234,6 +242,7 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
mBlit = new Blit(this);
mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
mSupportsVertexTexture = display->getVertexTextureSupport();
mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight),
(int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
@ -319,11 +328,21 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
void Context::markAllStateDirty()
{
for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++)
{
mAppliedTextureSerialPS[t] = 0;
}
for (int t = 0; t < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; t++)
{
mAppliedTextureSerialVS[t] = 0;
}
mAppliedProgramSerial = 0;
mAppliedRenderTargetSerial = 0;
mAppliedDepthbufferSerial = 0;
mAppliedStencilbufferSerial = 0;
mDepthStencilInitialized = false;
mAppliedProgram = 0;
mClearStateDirty = true;
mCullStateDirty = true;
@ -710,7 +729,7 @@ void Context::setDepthMask(bool mask)
}
}
void Context::setActiveSampler(int active)
void Context::setActiveSampler(unsigned int active)
{
mState.activeSampler = active;
}
@ -814,12 +833,7 @@ GLuint Context::createRenderbuffer()
// Returns an unused framebuffer name
GLuint Context::createFramebuffer()
{
unsigned int handle = 1;
while (mFramebufferMap.find(handle) != mFramebufferMap.end())
{
handle++;
}
GLuint handle = mFramebufferHandleAllocator.allocate();
mFramebufferMap[handle] = NULL;
@ -828,12 +842,7 @@ GLuint Context::createFramebuffer()
GLuint Context::createFence()
{
unsigned int handle = 0;
while (mFenceMap.find(handle) != mFenceMap.end())
{
handle++;
}
GLuint handle = mFenceHandleAllocator.allocate();
mFenceMap[handle] = new Fence;
@ -888,6 +897,7 @@ void Context::deleteFramebuffer(GLuint framebuffer)
{
detachFramebuffer(framebuffer);
mFramebufferHandleAllocator.release(framebufferObject->first);
delete framebufferObject->second;
mFramebufferMap.erase(framebufferObject);
}
@ -899,6 +909,7 @@ void Context::deleteFence(GLuint fence)
if (fenceObject != mFenceMap.end())
{
mFenceHandleAllocator.release(fenceObject->first);
delete fenceObject->second;
mFenceMap.erase(fenceObject);
}
@ -955,16 +966,16 @@ void Context::bindElementArrayBuffer(unsigned int buffer)
void Context::bindTexture2D(GLuint texture)
{
mResourceManager->checkTextureAllocation(texture, SAMPLER_2D);
mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(getTexture(texture));
mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
}
void Context::bindTextureCubeMap(GLuint texture)
{
mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE);
mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(getTexture(texture));
mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
}
void Context::bindReadFramebuffer(GLuint framebuffer)
@ -1073,15 +1084,15 @@ Program *Context::getCurrentProgram()
Texture2D *Context::getTexture2D()
{
return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, SAMPLER_2D));
return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
}
TextureCubeMap *Context::getTextureCubeMap()
{
return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, SAMPLER_CUBE));
return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
}
Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
{
GLuint texid = mState.samplerTexture[type][sampler].id();
@ -1090,8 +1101,8 @@ Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
switch (type)
{
default: UNREACHABLE();
case SAMPLER_2D: return mTexture2DZero.get();
case SAMPLER_CUBE: return mTextureCubeMapZero.get();
case TEXTURE_2D: return mTexture2DZero.get();
case TEXTURE_CUBE: return mTextureCubeMapZero.get();
}
}
@ -1183,8 +1194,8 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break;
case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = getMaximumCombinedTextureImageUnits(); break;
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = getMaximumVertexTextureImageUnits(); break;
case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break;
case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break;
@ -1372,24 +1383,24 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
break;
case GL_TEXTURE_BINDING_2D:
{
if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
{
error(GL_INVALID_OPERATION);
return false;
}
*params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler].id();
*params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
}
break;
case GL_TEXTURE_BINDING_CUBE_MAP:
{
if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
{
error(GL_INVALID_OPERATION);
return false;
}
*params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].id();
*params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
}
break;
default:
@ -1572,9 +1583,7 @@ bool Context::applyRenderTarget(bool ignoreViewport)
if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
error(GL_INVALID_FRAMEBUFFER_OPERATION);
return false;
return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
}
IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
@ -1743,7 +1752,7 @@ void Context::applyState(GLenum drawMode)
if (mDepthStateDirty)
{
if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
if (mState.depthTest)
{
device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
@ -1788,7 +1797,6 @@ void Context::applyState(GLenum drawMode)
device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
}
else
{
@ -1951,33 +1959,17 @@ void Context::applyState(GLenum drawMode)
mFrontFaceDirty = false;
}
// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
{
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (attributes[i].active)
{
attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
}
}
}
GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
{
TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
GLenum err = mVertexDataManager->prepareVertexData(first, count, translated);
GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes);
if (err != GL_NO_ERROR)
{
return err;
}
lookupAttributeMapping(translated);
mVertexDataManager->setupAttributes(translated);
return GL_NO_ERROR;
return mVertexDeclarationCache.applyDeclaration(attributes, getCurrentProgram());
}
// Applies the indices and element array bindings to the Direct3D 9 device
@ -2005,11 +1997,10 @@ void Context::applyShaders()
device->SetVertexShader(vertexShader);
device->SetPixelShader(pixelShader);
if (programObject->getSerial() != mAppliedProgram)
if (programObject->getSerial() != mAppliedProgramSerial)
{
programObject->dirtyAllUniforms();
programObject->dirtyAllSamplers();
mAppliedProgram = programObject->getSerial();
mAppliedProgramSerial = programObject->getSerial();
}
programObject->applyUniforms();
@ -2017,53 +2008,80 @@ void Context::applyShaders()
// Applies the textures and sampler states to the Direct3D 9 device
void Context::applyTextures()
{
applyTextures(SAMPLER_PIXEL);
if (mSupportsVertexTexture)
{
applyTextures(SAMPLER_VERTEX);
}
}
// For each Direct3D 9 sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive).
void Context::applyTextures(SamplerType type)
{
IDirect3DDevice9 *device = getDevice();
Program *programObject = getCurrentProgram();
for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; // Range of Direct3D 9 samplers of given sampler type
for (int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++)
{
int textureUnit = programObject->getSamplerMapping(sampler);
int textureUnit = programObject->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index
int d3dSampler = (type == SAMPLER_PIXEL) ? samplerIndex : D3DVERTEXTEXTURESAMPLER0 + samplerIndex;
unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS;
if (textureUnit != -1)
{
SamplerType textureType = programObject->getSamplerType(sampler);
TextureType textureType = programObject->getSamplerTextureType(type, samplerIndex);
Texture *texture = getSamplerTexture(textureUnit, textureType);
if (programObject->isSamplerDirty(sampler) || texture->isDirty())
if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter() || texture->isDirtyImage())
{
if (texture->isComplete())
IDirect3DBaseTexture9 *d3dTexture = texture->getTexture();
if (d3dTexture)
{
if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter())
{
GLenum wrapS = texture->getWrapS();
GLenum wrapT = texture->getWrapT();
GLenum minFilter = texture->getMinFilter();
GLenum magFilter = texture->getMagFilter();
device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
device->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
device->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
device->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
device->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
device->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
}
device->SetTexture(sampler, texture->getTexture());
if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyImage())
{
device->SetTexture(d3dSampler, d3dTexture);
}
}
else
{
device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
}
device->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture());
}
programObject->setSamplerDirty(sampler, false);
appliedTextureSerial[samplerIndex] = texture->getSerial();
texture->resetDirty();
}
}
else
{
if (programObject->isSamplerDirty(sampler))
if (appliedTextureSerial[samplerIndex] != 0)
{
device->SetTexture(sampler, NULL);
programObject->setSamplerDirty(sampler, false);
device->SetTexture(d3dSampler, NULL);
appliedTextureSerial[samplerIndex] = 0;
}
}
}
@ -2333,9 +2351,7 @@ void Context::clear(GLbitfield mask)
if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
error(GL_INVALID_FRAMEBUFFER_OPERATION);
return;
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
}
egl::Display *display = getDisplay();
@ -2378,7 +2394,7 @@ void Context::clear(GLbitfield mask)
D3DSURFACE_DESC desc;
depthStencil->GetDesc(&desc);
unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
unsigned int stencilSize = dx2es::GetStencilSize(desc.Format);
stencilUnmasked = (0x1 << stencilSize) - 1;
if (stencilUnmasked != 0x0)
@ -2415,7 +2431,7 @@ void Context::clear(GLbitfield mask)
D3DSURFACE_DESC desc;
renderTarget->GetDesc(&desc);
bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
bool alphaUnmasked = (dx2es::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
(mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
@ -2447,7 +2463,13 @@ void Context::clear(GLbitfield mask)
device->SetPixelShader(NULL);
device->SetVertexShader(NULL);
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
device->SetRenderState(D3DRS_TEXTUREFACTOR, color);
device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
hr = device->EndStateBlock(&mMaskedClearSavedState);
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
@ -2472,10 +2494,7 @@ void Context::clear(GLbitfield mask)
if (flags & D3DCLEAR_TARGET)
{
device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
(mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
(mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
(mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));
}
else
{
@ -2501,42 +2520,38 @@ void Context::clear(GLbitfield mask)
device->SetPixelShader(NULL);
device->SetVertexShader(NULL);
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
device->SetFVF(D3DFVF_XYZRHW);
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
device->SetRenderState(D3DRS_TEXTUREFACTOR, color);
device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
struct Vertex
{
float x, y, z, w;
D3DCOLOR diffuse;
};
float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
quad[0][0] = -0.5f;
quad[0][1] = desc.Height - 0.5f;
quad[0][2] = 0.0f;
quad[0][3] = 1.0f;
Vertex quad[4];
quad[0].x = 0.0f;
quad[0].y = (float)desc.Height;
quad[0].z = 0.0f;
quad[0].w = 1.0f;
quad[0].diffuse = color;
quad[1][0] = desc.Width - 0.5f;
quad[1][1] = desc.Height - 0.5f;
quad[1][2] = 0.0f;
quad[1][3] = 1.0f;
quad[1].x = (float)desc.Width;
quad[1].y = (float)desc.Height;
quad[1].z = 0.0f;
quad[1].w = 1.0f;
quad[1].diffuse = color;
quad[2][0] = -0.5f;
quad[2][1] = -0.5f;
quad[2][2] = 0.0f;
quad[2][3] = 1.0f;
quad[2].x = 0.0f;
quad[2].y = 0.0f;
quad[2].z = 0.0f;
quad[2].w = 1.0f;
quad[2].diffuse = color;
quad[3].x = (float)desc.Width;
quad[3].y = 0.0f;
quad[3].z = 0.0f;
quad[3].w = 1.0f;
quad[3].diffuse = color;
quad[3][0] = desc.Width - 0.5f;
quad[3][1] = -0.5f;
quad[3][2] = 0.0f;
quad[3][3] = 1.0f;
display->startScene();
device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
if (flags & D3DCLEAR_ZBUFFER)
{
@ -2592,7 +2607,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
applyShaders();
applyTextures();
if (!getCurrentProgram()->validateSamplers())
if (!getCurrentProgram()->validateSamplers(false))
{
return error(GL_INVALID_OPERATION);
}
@ -2659,7 +2674,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
applyShaders();
applyTextures();
if (!getCurrentProgram()->validateSamplers())
if (!getCurrentProgram()->validateSamplers(false))
{
return error(GL_INVALID_OPERATION);
}
@ -2682,23 +2697,44 @@ void Context::finish()
egl::Display *display = getDisplay();
IDirect3DDevice9 *device = getDevice();
IDirect3DQuery9 *occlusionQuery = NULL;
HRESULT result;
HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
if (FAILED(result))
{
ERR("CreateQuery failed hr=%x\n", result);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(GL_OUT_OF_MEMORY);
}
ASSERT(false);
return;
}
IDirect3DStateBlock9 *savedState = NULL;
result = device->CreateStateBlock(D3DSBT_ALL, &savedState);
if (FAILED(result))
{
ERR("CreateStateBlock failed hr=%x\n", result);
occlusionQuery->Release();
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(GL_OUT_OF_MEMORY);
}
ASSERT(false);
return;
}
ASSERT(SUCCEEDED(result));
if (occlusionQuery)
result = occlusionQuery->Issue(D3DISSUE_BEGIN);
if (FAILED(result))
{
IDirect3DStateBlock9 *savedState = NULL;
device->CreateStateBlock(D3DSBT_ALL, &savedState);
HRESULT result = occlusionQuery->Issue(D3DISSUE_BEGIN);
ASSERT(SUCCEEDED(result));
ERR("occlusionQuery->Issue(BEGIN) failed hr=%x\n", result);
occlusionQuery->Release();
savedState->Release();
ASSERT(false);
return;
}
// Render something outside the render target
device->SetPixelShader(NULL);
@ -2709,21 +2745,29 @@ void Context::finish()
device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
result = occlusionQuery->Issue(D3DISSUE_END);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
ERR("occlusionQuery->Issue(END) failed hr=%x\n", result);
occlusionQuery->Release();
savedState->Apply();
savedState->Release();
ASSERT(false);
return;
}
while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
while ((result = occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH)) == S_FALSE)
{
// Keep polling, but allow other threads to do something useful first
Sleep(0);
}
occlusionQuery->Release();
if (savedState)
{
savedState->Apply();
savedState->Release();
}
if (result == D3DERR_DEVICELOST)
{
error(GL_OUT_OF_MEMORY);
}
}
@ -2731,20 +2775,28 @@ void Context::flush()
{
IDirect3DDevice9 *device = getDevice();
IDirect3DQuery9 *eventQuery = NULL;
HRESULT result;
HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
if (FAILED(result))
{
ERR("CreateQuery failed hr=%x\n", result);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(GL_OUT_OF_MEMORY);
}
ASSERT(false);
return;
}
ASSERT(SUCCEEDED(result));
if (eventQuery)
result = eventQuery->Issue(D3DISSUE_END);
if (FAILED(result))
{
HRESULT result = eventQuery->Issue(D3DISSUE_END);
ASSERT(SUCCEEDED(result));
ERR("eventQuery->Issue(END) failed hr=%x\n", result);
ASSERT(false);
eventQuery->Release();
return;
}
result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
eventQuery->Release();
@ -2754,55 +2806,62 @@ void Context::flush()
error(GL_OUT_OF_MEMORY);
}
}
}
void Context::drawClosingLine(unsigned int first, unsigned int last)
{
IDirect3DDevice9 *device = getDevice();
IDirect3DIndexBuffer9 *indexBuffer = NULL;
HRESULT result = D3DERR_INVALIDCALL;
bool succeeded = false;
UINT offset;
if (supports32bitIndices())
{
result = device->CreateIndexBuffer(8, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &indexBuffer, 0);
const int spaceNeeded = 2 * sizeof(unsigned int);
if (SUCCEEDED(result))
if (!mClosingIB)
{
unsigned int *data;
result = indexBuffer->Lock(0, 0, (void**)&data, 0);
mClosingIB = new StreamingIndexBuffer(device, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
}
if (SUCCEEDED(result))
mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
unsigned int *data = static_cast<unsigned int*>(mClosingIB->map(spaceNeeded, &offset));
if (data)
{
data[0] = last;
data[1] = first;
}
mClosingIB->unmap();
offset /= 4;
succeeded = true;
}
}
else
{
result = device->CreateIndexBuffer(4, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, 0);
const int spaceNeeded = 2 * sizeof(unsigned short);
if (SUCCEEDED(result))
if (!mClosingIB)
{
unsigned short *data;
result = indexBuffer->Lock(0, 0, (void**)&data, 0);
mClosingIB = new StreamingIndexBuffer(device, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
}
if (SUCCEEDED(result))
mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
unsigned short *data = static_cast<unsigned short*>(mClosingIB->map(spaceNeeded, &offset));
if (data)
{
data[0] = last;
data[1] = first;
}
mClosingIB->unmap();
offset /= 2;
succeeded = true;
}
}
if (SUCCEEDED(result))
if (succeeded)
{
indexBuffer->Unlock();
device->SetIndices(indexBuffer);
device->SetIndices(mClosingIB->getBuffer());
device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 2, 0, 1);
indexBuffer->Release();
device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 2, offset, 1);
}
else
{
@ -2920,6 +2979,16 @@ int Context::getMaximumVaryingVectors() const
return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
}
unsigned int Context::getMaximumVertexTextureImageUnits() const
{
return mSupportsVertexTexture ? MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF : 0;
}
unsigned int Context::getMaximumCombinedTextureImageUnits() const
{
return MAX_TEXTURE_IMAGE_UNITS + getMaximumVertexTextureImageUnits();
}
int Context::getMaximumFragmentUniformVectors() const
{
return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2;
@ -3060,9 +3129,9 @@ void Context::detachTexture(GLuint texture)
// If a texture object is deleted, it is as if all texture units which are bound to that texture object are
// rebound to texture object zero
for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
{
for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
{
if (mState.samplerTexture[type][sampler].id() == texture)
{
@ -3137,7 +3206,7 @@ void Context::detachRenderbuffer(GLuint renderbuffer)
}
}
Texture *Context::getIncompleteTexture(SamplerType type)
Texture *Context::getIncompleteTexture(TextureType type)
{
Texture *t = mIncompleteTextures[type].get();
@ -3149,26 +3218,26 @@ Texture *Context::getIncompleteTexture(SamplerType type)
{
default:
UNREACHABLE();
// default falls through to SAMPLER_2D
// default falls through to TEXTURE_2D
case SAMPLER_2D:
case TEXTURE_2D:
{
Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
t = incomplete2d;
}
break;
case SAMPLER_CUBE:
case TEXTURE_CUBE:
{
TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
t = incompleteCube;
}
@ -3552,6 +3621,88 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
}
}
VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
{
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
mVertexDeclCache[i].vertexDeclaration = NULL;
mVertexDeclCache[i].lruCount = 0;
}
}
VertexDeclarationCache::~VertexDeclarationCache()
{
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
if (mVertexDeclCache[i].vertexDeclaration)
{
mVertexDeclCache[i].vertexDeclaration->Release();
}
}
}
GLenum VertexDeclarationCache::applyDeclaration(TranslatedAttribute attributes[], Program *program)
{
IDirect3DDevice9 *device = getDevice();
D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1];
D3DVERTEXELEMENT9 *element = &elements[0];
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (attributes[i].active)
{
device->SetStreamSource(i, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride);
element->Stream = i;
element->Offset = 0;
element->Type = attributes[i].type;
element->Method = D3DDECLMETHOD_DEFAULT;
element->Usage = D3DDECLUSAGE_TEXCOORD;
element->UsageIndex = program->getSemanticIndex(i);
element++;
}
}
static const D3DVERTEXELEMENT9 end = D3DDECL_END();
*(element++) = end;
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
{
entry->lruCount = ++mMaxLru;
device->SetVertexDeclaration(entry->vertexDeclaration);
return GL_NO_ERROR;
}
}
VertexDeclCacheEntry *lastCache = mVertexDeclCache;
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
{
lastCache = &mVertexDeclCache[i];
}
}
if (lastCache->vertexDeclaration != NULL)
{
lastCache->vertexDeclaration->Release();
lastCache->vertexDeclaration = NULL;
}
memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
device->SetVertexDeclaration(lastCache->vertexDeclaration);
lastCache->lruCount = ++mMaxLru;
return GL_NO_ERROR;
}
}
extern "C"

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -18,9 +18,11 @@
#include <d3d9.h>
#include <map>
#include <hash_map>
#include "common/angleutils.h"
#include "libGLESv2/ResourceManager.h"
#include "libGLESv2/HandleAllocator.h"
#include "libGLESv2/RefCountObject.h"
namespace egl
@ -46,6 +48,7 @@ class Renderbuffer;
class RenderbufferStorage;
class Colorbuffer;
class Depthbuffer;
class StreamingIndexBuffer;
class Stencilbuffer;
class DepthStencilbuffer;
class VertexDataManager;
@ -59,9 +62,9 @@ enum
MAX_VERTEX_UNIFORM_VECTORS = 256 - 2, // 256 is the minimum for SM2, and in practice the maximum for DX9. Reserve space for dx_HalfPixelSize and dx_DepthRange.
MAX_VARYING_VECTORS_SM2 = 8,
MAX_VARYING_VECTORS_SM3 = 10,
MAX_COMBINED_TEXTURE_IMAGE_UNITS = 16,
MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0,
MAX_TEXTURE_IMAGE_UNITS = 16,
MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF = 4, // For devices supporting vertex texture fetch
MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF,
MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3, // Reserve space for dx_Viewport, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers.
MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3,
MAX_DRAW_BUFFERS = 1,
@ -203,7 +206,7 @@ struct State
bool colorMaskAlpha;
bool depthMask;
int activeSampler; // Active texture unit selector - GL_TEXTURE0
unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0
BindingPointer<Buffer> arrayBuffer;
BindingPointer<Buffer> elementArrayBuffer;
GLuint readFramebuffer;
@ -212,12 +215,34 @@ struct State
GLuint currentProgram;
VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
BindingPointer<Texture> samplerTexture[SAMPLER_TYPE_COUNT][MAX_TEXTURE_IMAGE_UNITS];
BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
GLint unpackAlignment;
GLint packAlignment;
};
// Helper class to construct and cache vertex declarations
class VertexDeclarationCache
{
public:
VertexDeclarationCache();
~VertexDeclarationCache();
GLenum applyDeclaration(TranslatedAttribute attributes[], Program *program);
private:
UINT mMaxLru;
enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 16 };
struct VertexDeclCacheEntry
{
D3DVERTEXELEMENT9 cachedElements[MAX_VERTEX_ATTRIBS + 1];
UINT lruCount;
IDirect3DVertexDeclaration9 *vertexDeclaration;
} mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
};
class Context
{
public:
@ -298,7 +323,7 @@ class Context
void setColorMask(bool red, bool green, bool blue, bool alpha);
void setDepthMask(bool mask);
void setActiveSampler(int active);
void setActiveSampler(unsigned int active);
GLuint getReadFramebufferHandle() const;
GLuint getDrawFramebufferHandle() const;
@ -370,7 +395,7 @@ class Context
Program *getCurrentProgram();
Texture2D *getTexture2D();
TextureCubeMap *getTextureCubeMap();
Texture *getSamplerTexture(unsigned int sampler, SamplerType type);
Texture *getSamplerTexture(unsigned int sampler, TextureType type);
Framebuffer *getReadFramebuffer();
Framebuffer *getDrawFramebuffer();
@ -380,13 +405,6 @@ class Context
bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
bool applyRenderTarget(bool ignoreViewport);
void applyState(GLenum drawMode);
GLenum applyVertexBuffer(GLint first, GLsizei count);
GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
void applyShaders();
void applyTextures();
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
void clear(GLbitfield mask);
void drawArrays(GLenum mode, GLint first, GLsizei count);
@ -408,6 +426,8 @@ class Context
bool supportsShaderModel3() const;
int getMaximumVaryingVectors() const;
unsigned int getMaximumVertexTextureImageUnits() const;
unsigned int getMaximumCombinedTextureImageUnits() const;
int getMaximumFragmentUniformVectors() const;
int getMaximumRenderbufferDimension() const;
int getMaximumTextureDimension() const;
@ -439,14 +459,20 @@ class Context
private:
DISALLOW_COPY_AND_ASSIGN(Context);
void lookupAttributeMapping(TranslatedAttribute *attributes);
bool applyRenderTarget(bool ignoreViewport);
void applyState(GLenum drawMode);
GLenum applyVertexBuffer(GLint first, GLsizei count);
GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
void applyShaders();
void applyTextures();
void applyTextures(SamplerType type);
void detachBuffer(GLuint buffer);
void detachTexture(GLuint texture);
void detachFramebuffer(GLuint framebuffer);
void detachRenderbuffer(GLuint renderbuffer);
Texture *getIncompleteTexture(SamplerType type);
Texture *getIncompleteTexture(TextureType type);
bool cullSkipsDraw(GLenum drawMode);
bool isTriangleMode(GLenum drawMode);
@ -458,11 +484,13 @@ class Context
BindingPointer<Texture2D> mTexture2DZero;
BindingPointer<TextureCubeMap> mTextureCubeMapZero;
typedef std::map<GLuint, Framebuffer*> FramebufferMap;
typedef stdext::hash_map<GLuint, Framebuffer*> FramebufferMap;
FramebufferMap mFramebufferMap;
HandleAllocator mFramebufferHandleAllocator;
typedef std::map<GLuint, Fence*> FenceMap;
typedef stdext::hash_map<GLuint, Fence*> FenceMap;
FenceMap mFenceMap;
HandleAllocator mFenceHandleAllocator;
void initExtensionString();
std::string mExtensionString;
@ -472,7 +500,9 @@ class Context
Blit *mBlit;
BindingPointer<Texture> mIncompleteTextures[SAMPLER_TYPE_COUNT];
StreamingIndexBuffer *mClosingIB;
BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
// Recorded errors
bool mInvalidEnum;
@ -483,13 +513,16 @@ class Context
bool mHasBeenCurrent;
unsigned int mAppliedProgram;
unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS];
unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
unsigned int mAppliedProgramSerial;
unsigned int mAppliedRenderTargetSerial;
unsigned int mAppliedDepthbufferSerial;
unsigned int mAppliedStencilbufferSerial;
bool mDepthStencilInitialized;
bool mSupportsShaderModel3;
bool mSupportsVertexTexture;
int mMaxRenderbufferDimension;
int mMaxTextureDimension;
int mMaxCubeTextureDimension;
@ -527,6 +560,8 @@ class Context
D3DCAPS9 mDeviceCaps;
ResourceManager *mResourceManager;
VertexDeclarationCache mVertexDeclarationCache;
};
}
@ -538,6 +573,7 @@ void glDestroyContext(gl::Context *context);
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
gl::Context *glGetCurrentContext();
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
void __stdcall glBindTexImage(egl::Surface *surface);
}
#endif // INCLUDE_CONTEXT_H_

Просмотреть файл

@ -46,7 +46,7 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
}
else if (IsTextureTarget(type))
{
buffer = context->getTexture(handle)->getColorbuffer(type);
buffer = context->getTexture(handle)->getRenderbuffer(type);
}
else
{
@ -307,25 +307,25 @@ GLenum Framebuffer::completeness()
if (mColorbufferType == GL_RENDERBUFFER)
{
if (!gl::IsColorRenderable(colorbuffer->getFormat()))
if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
else if (IsTextureTarget(mColorbufferType))
{
if (IsCompressed(colorbuffer->getFormat()))
if (IsCompressed(colorbuffer->getInternalFormat()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
if (colorbuffer->isFloatingPoint() && (!getContext()->supportsFloatRenderableTextures() ||
!getContext()->supportsHalfFloatRenderableTextures()))
if ((colorbuffer->getType() == GL_FLOAT && !getContext()->supportsFloatRenderableTextures()) ||
(colorbuffer->getType() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatRenderableTextures()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
if (colorbuffer->getFormat() == GL_LUMINANCE || colorbuffer->getFormat() == GL_LUMINANCE_ALPHA)
if (colorbuffer->getInternalFormat() == GL_LUMINANCE || colorbuffer->getInternalFormat() == GL_LUMINANCE_ALPHA)
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
@ -424,8 +424,8 @@ GLenum Framebuffer::completeness()
if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER)
{
if (depthbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
stencilbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
if (depthbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
stencilbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
depthbuffer->getSerial() != stencilbuffer->getSerial())
{
return GL_FRAMEBUFFER_UNSUPPORTED;

Просмотреть файл

@ -0,0 +1,63 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
// to allocate GL handles.
#include "libGLESv2/HandleAllocator.h"
#include "libGLESv2/main.h"
namespace gl
{
HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1)
{
}
HandleAllocator::~HandleAllocator()
{
}
void HandleAllocator::setBaseHandle(GLuint value)
{
ASSERT(mBaseValue == mNextValue);
mBaseValue = value;
mNextValue = value;
}
GLuint HandleAllocator::allocate()
{
if (mFreeValues.size())
{
GLuint handle = mFreeValues.back();
mFreeValues.pop_back();
return handle;
}
return mNextValue++;
}
void HandleAllocator::release(GLuint handle)
{
if (handle == mNextValue - 1)
{
// Don't drop below base value
if(mNextValue > mBaseValue)
{
mNextValue--;
}
}
else
{
// Only free handles that we own - don't drop below the base value
if (handle >= mBaseValue)
{
mFreeValues.push_back(handle);
}
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to
// allocate GL handles.
#ifndef LIBGLESV2_HANDLEALLOCATOR_H_
#define LIBGLESV2_HANDLEALLOCATOR_H_
#define GL_APICALL
#include <GLES2/gl2.h>
#include <vector>
#include "common/angleutils.h"
namespace gl
{
class HandleAllocator
{
public:
HandleAllocator();
virtual ~HandleAllocator();
void setBaseHandle(GLuint value);
GLuint allocate();
void release(GLuint handle);
private:
DISALLOW_COPY_AND_ASSIGN(HandleAllocator);
GLuint mBaseValue;
GLuint mNextValue;
typedef std::vector<GLuint> HandleList;
HandleList mFreeValues;
};
}
#endif // LIBGLESV2_HANDLEALLOCATOR_H_

Просмотреть файл

@ -0,0 +1,404 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// IndexDataManager.cpp: Defines the IndexDataManager, a class that
// runs the Buffer translation process for index buffers.
#include "libGLESv2/IndexDataManager.h"
#include "common/debug.h"
#include "libGLESv2/Buffer.h"
#include "libGLESv2/mathutil.h"
#include "libGLESv2/main.h"
namespace
{
enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
}
namespace gl
{
IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device)
{
mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
if (context->supports32bitIndices())
{
mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
if (!mStreamingBufferInt)
{
// Don't leave it in a half-initialized state
delete mStreamingBufferShort;
mStreamingBufferShort = NULL;
}
}
else
{
mStreamingBufferInt = NULL;
}
if (!mStreamingBufferShort)
{
ERR("Failed to allocate the streaming index buffer(s).");
}
}
IndexDataManager::~IndexDataManager()
{
delete mStreamingBufferShort;
delete mStreamingBufferInt;
}
void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
{
if (type == GL_UNSIGNED_BYTE)
{
const GLubyte *in = static_cast<const GLubyte*>(input);
GLushort *out = static_cast<GLushort*>(output);
for (GLsizei i = 0; i < count; i++)
{
out[i] = in[i];
}
}
else if (type == GL_UNSIGNED_INT)
{
memcpy(output, input, count * sizeof(GLuint));
}
else if (type == GL_UNSIGNED_SHORT)
{
memcpy(output, input, count * sizeof(GLushort));
}
else UNREACHABLE();
}
template <class IndexType>
void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
{
*minIndex = indices[0];
*maxIndex = indices[0];
for (GLsizei i = 0; i < count; i++)
{
if (*minIndex > indices[i]) *minIndex = indices[i];
if (*maxIndex < indices[i]) *maxIndex = indices[i];
}
}
void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
{
if (type == GL_UNSIGNED_BYTE)
{
computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
}
else if (type == GL_UNSIGNED_INT)
{
computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
}
else if (type == GL_UNSIGNED_SHORT)
{
computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
}
else UNREACHABLE();
}
GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated)
{
if (!mStreamingBufferShort)
{
return GL_OUT_OF_MEMORY;
}
D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
intptr_t offset = reinterpret_cast<intptr_t>(indices);
bool alignedOffset = false;
if (buffer != NULL)
{
switch (type)
{
case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break;
case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break;
default: UNREACHABLE(); alignedOffset = false;
}
if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
{
return GL_INVALID_OPERATION;
}
indices = static_cast<const GLubyte*>(buffer->data()) + offset;
}
StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
IndexBuffer *indexBuffer = streamingBuffer;
UINT streamOffset = 0;
if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
{
indexBuffer = staticBuffer;
streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
if (streamOffset == -1)
{
streamOffset = (offset / typeSize(type)) * indexSize(format);
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
}
}
else
{
int convertCount = count;
if (staticBuffer)
{
if (staticBuffer->size() == 0 && alignedOffset)
{
indexBuffer = staticBuffer;
convertCount = buffer->size() / typeSize(type);
}
else
{
buffer->invalidateStaticData();
staticBuffer = NULL;
}
}
void *output = NULL;
if (indexBuffer)
{
indexBuffer->reserveSpace(convertCount * indexSize(format), type);
output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
}
if (output == NULL)
{
ERR("Failed to map index buffer.");
return GL_OUT_OF_MEMORY;
}
convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
indexBuffer->unmap();
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
if (staticBuffer)
{
streamOffset = (offset / typeSize(type)) * indexSize(format);
staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
}
}
translated->indexBuffer = indexBuffer->getBuffer();
translated->startIndex = streamOffset / indexSize(format);
if (buffer)
{
buffer->promoteStaticUsage(count * typeSize(type));
}
return GL_NO_ERROR;
}
std::size_t IndexDataManager::indexSize(D3DFORMAT format) const
{
return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short);
}
std::size_t IndexDataManager::typeSize(GLenum type) const
{
switch (type)
{
case GL_UNSIGNED_INT: return sizeof(GLuint);
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
default: UNREACHABLE(); return sizeof(GLushort);
}
}
IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL)
{
if (size > 0)
{
D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL);
if (FAILED(result))
{
ERR("Out of memory allocating an index buffer of size %lu.", size);
}
}
}
IndexBuffer::~IndexBuffer()
{
if (mIndexBuffer)
{
mIndexBuffer->Release();
}
}
IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const
{
return mIndexBuffer;
}
void IndexBuffer::unmap()
{
if (mIndexBuffer)
{
mIndexBuffer->Unlock();
}
}
StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format)
{
mWritePosition = 0;
}
StreamingIndexBuffer::~StreamingIndexBuffer()
{
}
void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset)
{
void *mapPtr = NULL;
if (mIndexBuffer)
{
HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
if (FAILED(result))
{
ERR(" Lock failed with error 0x%08x", result);
return NULL;
}
*offset = mWritePosition;
mWritePosition += requiredSpace;
}
return mapPtr;
}
void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
{
if (requiredSpace > mBufferSize)
{
if (mIndexBuffer)
{
mIndexBuffer->Release();
mIndexBuffer = NULL;
}
mBufferSize = std::max(requiredSpace, 2 * mBufferSize);
D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
if (FAILED(result))
{
ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
}
mWritePosition = 0;
}
else if (mWritePosition + requiredSpace > mBufferSize) // Recycle
{
void *dummy;
mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
mIndexBuffer->Unlock();
mWritePosition = 0;
}
}
StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN)
{
mCacheType = GL_NONE;
}
StaticIndexBuffer::~StaticIndexBuffer()
{
}
void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset)
{
void *mapPtr = NULL;
if (mIndexBuffer)
{
HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
if (FAILED(result))
{
ERR(" Lock failed with error 0x%08x", result);
return NULL;
}
*offset = 0;
}
return mapPtr;
}
void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
{
if (!mIndexBuffer && mBufferSize == 0)
{
D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY);
HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
if (FAILED(result))
{
ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
}
mBufferSize = requiredSpace;
mCacheType = type;
}
else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
{
// Already allocated
}
else UNREACHABLE(); // Static index buffers can't be resized
}
bool StaticIndexBuffer::lookupType(GLenum type)
{
return mCacheType == type;
}
UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
{
for (unsigned int range = 0; range < mCache.size(); range++)
{
if (mCache[range].offset == offset && mCache[range].count == count)
{
*minIndex = mCache[range].minIndex;
*maxIndex = mCache[range].maxIndex;
return mCache[range].streamOffset;
}
}
return -1;
}
void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset)
{
IndexRange indexRange = {offset, count, minIndex, maxIndex, streamOffset};
mCache.push_back(indexRange);
}
}

Просмотреть файл

@ -0,0 +1,120 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// IndexDataManager.h: Defines the IndexDataManager, a class that
// runs the Buffer translation process for index buffers.
#ifndef LIBGLESV2_INDEXDATAMANAGER_H_
#define LIBGLESV2_INDEXDATAMANAGER_H_
#include <vector>
#include <cstddef>
#define GL_APICALL
#include <GLES2/gl2.h>
#include "libGLESv2/Context.h"
namespace gl
{
struct TranslatedIndexData
{
UINT minIndex;
UINT maxIndex;
UINT startIndex;
IDirect3DIndexBuffer9 *indexBuffer;
};
class IndexBuffer
{
public:
IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format);
virtual ~IndexBuffer();
UINT size() const { return mBufferSize; }
virtual void *map(UINT requiredSpace, UINT *offset) = 0;
void unmap();
virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0;
IDirect3DIndexBuffer9 *getBuffer() const;
protected:
IDirect3DDevice9 *const mDevice;
IDirect3DIndexBuffer9 *mIndexBuffer;
UINT mBufferSize;
private:
DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
};
class StreamingIndexBuffer : public IndexBuffer
{
public:
StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format);
~StreamingIndexBuffer();
virtual void *map(UINT requiredSpace, UINT *offset);
virtual void reserveSpace(UINT requiredSpace, GLenum type);
private:
UINT mWritePosition;
};
class StaticIndexBuffer : public IndexBuffer
{
public:
explicit StaticIndexBuffer(IDirect3DDevice9 *device);
~StaticIndexBuffer();
virtual void *map(UINT requiredSpace, UINT *offset);
virtual void reserveSpace(UINT requiredSpace, GLenum type);
bool lookupType(GLenum type);
UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex); // Returns the offset into the index buffer, or -1 if not found
void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset);
private:
GLenum mCacheType;
struct IndexRange
{
intptr_t offset;
GLsizei count;
UINT minIndex;
UINT maxIndex;
UINT streamOffset;
};
std::vector<IndexRange> mCache;
};
class IndexDataManager
{
public:
IndexDataManager(Context *context, IDirect3DDevice9 *evice);
virtual ~IndexDataManager();
GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated);
private:
DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
std::size_t typeSize(GLenum type) const;
std::size_t indexSize(D3DFORMAT format) const;
IDirect3DDevice9 *const mDevice;
StreamingIndexBuffer *mStreamingBufferShort;
StreamingIndexBuffer *mStreamingBufferInt;
};
}
#endif // LIBGLESV2_INDEXDATAMANAGER_H_

Просмотреть файл

@ -91,6 +91,8 @@ CPPSRCS = \
ossource_win.cpp \
util.cpp \
ValidateLimitations.cpp \
ForLoopUnroll.cpp \
MapLongVariableNames.cpp \
$(NULL)
# flex/yacc generated files
@ -142,6 +144,9 @@ CPPSRCS += \
Shader.cpp \
Texture.cpp \
utilities.cpp \
HandleAllocator.cpp \
IndexDataManager.cpp \
VertexDataManager.cpp \
$(NULL)
DEFFILE = $(srcdir)/libGLESv2.def
@ -149,4 +154,6 @@ DEFFILE = $(srcdir)/libGLESv2.def
include $(topsrcdir)/config/rules.mk
EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/x86/d3d9.lib" "$(MOZ_DIRECTX_SDK_PATH)/lib/x86/d3dx9.lib"
EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/x86/d3d9.lib" \
"$(MOZ_DIRECTX_SDK_PATH)/lib/x86/d3dx9.lib" \
"$(MOZ_DIRECTX_SDK_PATH)/lib/x86/D3DCompiler.lib"

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -15,6 +15,10 @@
#include "libGLESv2/Shader.h"
#include "libGLESv2/utilities.h"
#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
#endif
namespace gl
{
unsigned int Program::mCurrentSerial = 1;
@ -182,28 +186,39 @@ GLuint Program::getAttributeLocation(const char *name)
int Program::getSemanticIndex(int attributeIndex)
{
if (attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS)
{
ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
return mSemanticIndex[attributeIndex];
}
return -1;
// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
// index (0-15 for the pixel shader and 0-3 for the vertex shader).
GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
{
GLuint logicalTextureUnit = -1;
switch (type)
{
case SAMPLER_PIXEL:
ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
if (mSamplersPS[samplerIndex].active)
{
logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
}
break;
case SAMPLER_VERTEX:
ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
if (mSamplersVS[samplerIndex].active)
{
logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
}
break;
default: UNREACHABLE();
}
// Returns the index of the texture unit corresponding to a Direct3D 9 sampler
// index referenced in the compiled HLSL shader
GLint Program::getSamplerMapping(unsigned int samplerIndex)
{
assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
GLint logicalTextureUnit = -1;
if (mSamplers[samplerIndex].active)
{
logicalTextureUnit = mSamplers[samplerIndex].logicalTextureUnit;
}
if (logicalTextureUnit >= 0 && logicalTextureUnit < MAX_TEXTURE_IMAGE_UNITS)
if (logicalTextureUnit >= 0 && logicalTextureUnit < getContext()->getMaximumCombinedTextureImageUnits())
{
return logicalTextureUnit;
}
@ -211,32 +226,24 @@ GLint Program::getSamplerMapping(unsigned int samplerIndex)
return -1;
}
SamplerType Program::getSamplerType(unsigned int samplerIndex)
// Returns the texture type for a given Direct3D 9 sampler type and
// index (0-15 for the pixel shader and 0-3 for the vertex shader).
TextureType Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
{
assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
assert(mSamplers[samplerIndex].active);
return mSamplers[samplerIndex].type;
switch (type)
{
case SAMPLER_PIXEL:
ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
ASSERT(mSamplersPS[samplerIndex].active);
return mSamplersPS[samplerIndex].textureType;
case SAMPLER_VERTEX:
ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
ASSERT(mSamplersVS[samplerIndex].active);
return mSamplersVS[samplerIndex].textureType;
default: UNREACHABLE();
}
bool Program::isSamplerDirty(unsigned int samplerIndex) const
{
if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
{
return mSamplers[samplerIndex].dirty;
}
else UNREACHABLE();
return false;
}
void Program::setSamplerDirty(unsigned int samplerIndex, bool dirty)
{
if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
{
mSamplers[samplerIndex].dirty = dirty;
}
else UNREACHABLE();
return TEXTURE_2D;
}
GLint Program::getUniformLocation(const char *name, bool decorated)
@ -904,14 +911,6 @@ void Program::dirtyAllUniforms()
}
}
void Program::dirtyAllSamplers()
{
for (unsigned int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; ++index)
{
mSamplers[index].dirty = true;
}
}
// Applies all the uniforms set for this program object to the Direct3D 9 device
void Program::applyUniforms()
{
@ -961,44 +960,38 @@ void Program::applyUniforms()
}
// Compiles the HLSL code of the attached shaders into executable binaries
ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
ID3D10Blob *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
{
if (!hlsl)
{
return NULL;
}
ID3DXBuffer *binary = NULL;
ID3DXBuffer *errorMessage = NULL;
DWORD result;
UINT flags = 0;
std::string sourceText;
if (perfActive())
{
DWORD flags = D3DXSHADER_DEBUG;
#ifndef NDEBUG
flags |= D3DXSHADER_SKIPOPTIMIZATION;
flags |= D3DCOMPILE_DEBUG;
#ifdef NDEBUG
flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
#else
flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
std::string sourcePath = getTempPath();
std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
result = D3DXCompileShader(sourceText.c_str(), sourceText.size(), NULL, NULL, "main", profile, flags, &binary, &errorMessage, constantTable);
}
else
{
result = D3DXCompileShader(hlsl, (UINT)strlen(hlsl), NULL, NULL, "main", profile, 0, &binary, &errorMessage, constantTable);
flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
sourceText = hlsl;
}
if (SUCCEEDED(result))
{
return binary;
}
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(GL_OUT_OF_MEMORY, (ID3DXBuffer*)NULL);
}
ID3D10Blob *binary = NULL;
ID3D10Blob *errorMessage = NULL;
result = D3DCompile(hlsl, strlen(hlsl), NULL, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage);
if (errorMessage)
{
@ -1007,11 +1000,39 @@ ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3
appendToInfoLog("%s\n", message);
TRACE("\n%s", hlsl);
TRACE("\n%s", message);
errorMessage->Release();
errorMessage = NULL;
}
if (FAILED(result))
{
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
error(GL_OUT_OF_MEMORY);
}
return NULL;
}
result = D3DXGetShaderConstantTable(static_cast<const DWORD*>(binary->GetBufferPointer()), constantTable);
if (FAILED(result))
{
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
error(GL_OUT_OF_MEMORY);
}
binary->Release();
return NULL;
}
return binary;
}
// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Returns the number of used varying registers, or -1 if unsuccesful
int Program::packVaryings(const Varying *packing[][4])
@ -1110,13 +1131,13 @@ int Program::packVaryings(const Varying *packing[][4])
for (int x = 0; x < 4; x++)
{
if (space[x] > n && space[x] < space[column])
if (space[x] >= n && space[x] < space[column])
{
column = x;
}
}
if (space[column] > n)
if (space[column] >= n)
{
for (int r = 0; r < maxVaryingVectors; r++)
{
@ -1169,6 +1190,20 @@ bool Program::linkVaryings()
return false;
}
// Reset the varying register assignments
for (VaryingList::iterator fragVar = mFragmentShader->varyings.begin(); fragVar != mFragmentShader->varyings.end(); fragVar++)
{
fragVar->reg = -1;
fragVar->col = -1;
}
for (VaryingList::iterator vtxVar = mVertexShader->varyings.begin(); vtxVar != mVertexShader->varyings.end(); vtxVar++)
{
vtxVar->reg = -1;
vtxVar->col = -1;
}
// Map the varyings to the register file
const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
int registers = packVaryings(packing);
@ -1177,6 +1212,7 @@ bool Program::linkVaryings()
return false;
}
// Write the HLSL input/output declarations
Context *context = getContext();
const bool sm3 = context->supportsShaderModel3();
const int maxVaryingVectors = context->getMaximumVaryingVectors();
@ -1213,7 +1249,7 @@ bool Program::linkVaryings()
if (!matched)
{
appendToInfoLog("Fragment varying varying %s does not match any vertex varying", input->name.c_str());
appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
return false;
}
@ -1420,8 +1456,8 @@ bool Program::linkVaryings()
{
mPixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
if (sm3) {
mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n"
" gl_FragCoord.y = 2.0 * dx_Viewport.y - input.dx_VPos.y;\n";
mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
" gl_FragCoord.y = 2.0 * dx_Viewport.y - input.dx_VPos.y - 0.5;\n";
} else {
mPixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Viewport.x + dx_Viewport.z;\n"
" gl_FragCoord.y = -(input.gl_FragCoord.y * rhw) * dx_Viewport.y + dx_Viewport.w;\n";
@ -1510,8 +1546,8 @@ void Program::link()
const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
ID3DXBuffer *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
ID3DXBuffer *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
ID3D10Blob *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
ID3D10Blob *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
if (vertexBinary && pixelBinary)
{
@ -1656,7 +1692,8 @@ bool Program::linkUniforms(ID3DXConstantTable *constantTable)
for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
{
D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
HRESULT result = constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
ASSERT(SUCCEEDED(result));
if (!defineUniform(constantHandle, constantDescription))
{
@ -1675,12 +1712,35 @@ bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT
{
for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++)
{
ASSERT(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
if (mConstantTablePS->GetConstantByName(NULL, constantDescription.Name) != NULL)
{
if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
{
mSamplersPS[samplerIndex].active = true;
mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
mSamplersPS[samplerIndex].logicalTextureUnit = 0;
}
else
{
appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
return false;
}
}
mSamplers[samplerIndex].active = true;
mSamplers[samplerIndex].type = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? SAMPLER_CUBE : SAMPLER_2D;
mSamplers[samplerIndex].logicalTextureUnit = 0;
mSamplers[samplerIndex].dirty = true;
if (mConstantTableVS->GetConstantByName(NULL, constantDescription.Name) != NULL)
{
if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
{
mSamplersVS[samplerIndex].active = true;
mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
mSamplersVS[samplerIndex].logicalTextureUnit = 0;
}
else
{
appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
return false;
}
}
}
}
@ -1697,7 +1757,8 @@ bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT
D3DXCONSTANT_DESC fieldDescription;
UINT descriptionCount = 1;
mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
ASSERT(SUCCEEDED(result));
std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
@ -2230,11 +2291,7 @@ bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
D3DXCONSTANT_DESC constantDescription;
UINT descriptionCount = 1;
HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
if (FAILED(result))
{
return false;
}
ASSERT(SUCCEEDED(result));
if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
{
@ -2246,25 +2303,44 @@ bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
{
ASSERT(mSamplers[samplerIndex].active);
mSamplers[samplerIndex].logicalTextureUnit = v[i];
mSamplers[samplerIndex].dirty = true;
ASSERT(mSamplersPS[samplerIndex].active);
mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
}
}
return true;
}
}
if (constantPS)
else
{
mConstantTablePS->SetIntArray(device, constantPS, v, count);
}
}
if (constantVS)
{
D3DXCONSTANT_DESC constantDescription;
UINT descriptionCount = 1;
HRESULT result = mConstantTableVS->GetConstantDesc(constantVS, &constantDescription, &descriptionCount);
ASSERT(SUCCEEDED(result));
if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
{
unsigned int firstIndex = mConstantTableVS->GetSamplerIndex(constantVS);
for (int i = 0; i < count; i++)
{
unsigned int samplerIndex = firstIndex + i;
if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
{
ASSERT(mSamplersVS[samplerIndex].active);
mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
}
}
}
else
{
mConstantTableVS->SetIntArray(device, constantVS, v, count);
}
}
return true;
}
@ -2460,8 +2536,12 @@ void Program::unlink(bool destroy)
for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
{
mSamplers[index].active = false;
mSamplers[index].dirty = true;
mSamplersPS[index].active = false;
}
for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
{
mSamplersVS[index].active = false;
}
while (!mUniforms.empty())
@ -2766,9 +2846,8 @@ void Program::validate()
else
{
applyUniforms();
if (!validateSamplers())
if (!validateSamplers(true))
{
appendToInfoLog("Samplers of conflicting types refer to the same texture image unit.");
mValidated = false;
}
else
@ -2778,24 +2857,86 @@ void Program::validate()
}
}
bool Program::validateSamplers() const
bool Program::validateSamplers(bool logErrors)
{
// if any two active samplers in a program are of different types, but refer to the same
// texture image unit, and this is the current program, then ValidateProgram will fail, and
// DrawArrays and DrawElements will issue the INVALID_OPERATION error.
std::map<int, SamplerType> samplerMap;
const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
{
textureUnitType[i] = TEXTURE_UNKNOWN;
}
for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
{
if (mSamplers[i].active)
if (mSamplersPS[i].active)
{
if (samplerMap.find(mSamplers[i].logicalTextureUnit) != samplerMap.end())
unsigned int unit = mSamplersPS[i].logicalTextureUnit;
if (unit >= maxCombinedTextureImageUnits)
{
if (mSamplers[i].type != samplerMap[mSamplers[i].logicalTextureUnit])
if (logErrors)
{
appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
}
return false;
}
if (textureUnitType[unit] != TEXTURE_UNKNOWN)
{
if (mSamplersPS[i].textureType != textureUnitType[unit])
{
if (logErrors)
{
appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
}
return false;
}
}
else
{
samplerMap[mSamplers[i].logicalTextureUnit] = mSamplers[i].type;
textureUnitType[unit] = mSamplersPS[i].textureType;
}
}
}
for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
{
if (mSamplersVS[i].active)
{
unsigned int unit = mSamplersVS[i].logicalTextureUnit;
if (unit >= maxCombinedTextureImageUnits)
{
if (logErrors)
{
appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
}
return false;
}
if (textureUnitType[unit] != TEXTURE_UNKNOWN)
{
if (mSamplersVS[i].textureType != textureUnitType[unit])
{
if (logErrors)
{
appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
}
return false;
}
}
else
{
textureUnitType[unit] = mSamplersVS[i].textureType;
}
}
}

Просмотреть файл

@ -11,6 +11,7 @@
#define LIBGLESV2_PROGRAM_H_
#include <d3dx9.h>
#include <d3dcompiler.h>
#include <string>
#include <vector>
#include <set>
@ -71,12 +72,8 @@ class Program
GLuint getAttributeLocation(const char *name);
int getSemanticIndex(int attributeIndex);
void dirtyAllSamplers();
GLint getSamplerMapping(unsigned int samplerIndex);
SamplerType getSamplerType(unsigned int samplerIndex);
bool isSamplerDirty(unsigned int samplerIndex) const;
void setSamplerDirty(unsigned int samplerIndex, bool dirty);
GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex);
TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
GLint getUniformLocation(const char *name, bool decorated);
bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
@ -125,7 +122,7 @@ class Program
bool isFlaggedForDeletion() const;
void validate();
bool validateSamplers() const;
bool validateSamplers(bool logErrors);
bool isValidated() const;
unsigned int getSerial() const;
@ -133,7 +130,7 @@ class Program
private:
DISALLOW_COPY_AND_ASSIGN(Program);
ID3DXBuffer *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable);
ID3D10Blob *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable);
void unlink(bool destroy = false);
int packVaryings(const Varying *packing[][4]);
@ -191,11 +188,11 @@ class Program
{
bool active;
GLint logicalTextureUnit;
SamplerType type;
bool dirty;
TextureType textureType;
};
Sampler mSamplers[MAX_TEXTURE_IMAGE_UNITS];
Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
Sampler mSamplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
typedef std::vector<Uniform*> UniformArray;
UniformArray mUniforms;

Просмотреть файл

@ -54,24 +54,54 @@ IDirect3DSurface9 *Renderbuffer::getDepthStencil()
return mStorage->getDepthStencil();
}
int Renderbuffer::getWidth() const
GLsizei Renderbuffer::getWidth() const
{
return mStorage->getWidth();
}
int Renderbuffer::getHeight() const
GLsizei Renderbuffer::getHeight() const
{
return mStorage->getHeight();
}
GLenum Renderbuffer::getFormat() const
GLenum Renderbuffer::getInternalFormat() const
{
return mStorage->getFormat();
return mStorage->getInternalFormat();
}
D3DFORMAT Renderbuffer::getD3DFormat() const
GLuint Renderbuffer::getRedSize() const
{
return mStorage->getD3DFormat();
return mStorage->getRedSize();
}
GLuint Renderbuffer::getGreenSize() const
{
return mStorage->getGreenSize();
}
GLuint Renderbuffer::getBlueSize() const
{
return mStorage->getBlueSize();
}
GLuint Renderbuffer::getAlphaSize() const
{
return mStorage->getAlphaSize();
}
GLuint Renderbuffer::getDepthSize() const
{
return mStorage->getDepthSize();
}
GLuint Renderbuffer::getStencilSize() const
{
return mStorage->getStencilSize();
}
GLsizei Renderbuffer::getSamples() const
{
return mStorage->getSamples();
}
unsigned int Renderbuffer::getSerial() const
@ -91,7 +121,7 @@ RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial())
{
mWidth = 0;
mHeight = 0;
mFormat = GL_RGBA4;
mInternalFormat = GL_RGBA4;
mD3DFormat = D3DFMT_A8R8G8B8;
mSamples = 0;
}
@ -125,35 +155,49 @@ IDirect3DSurface9 *RenderbufferStorage::getDepthStencil()
return NULL;
}
int RenderbufferStorage::getWidth() const
GLsizei RenderbufferStorage::getWidth() const
{
return mWidth;
}
int RenderbufferStorage::getHeight() const
GLsizei RenderbufferStorage::getHeight() const
{
return mHeight;
}
void RenderbufferStorage::setSize(int width, int height)
GLenum RenderbufferStorage::getInternalFormat() const
{
mWidth = width;
mHeight = height;
return mInternalFormat;
}
GLenum RenderbufferStorage::getFormat() const
GLuint RenderbufferStorage::getRedSize() const
{
return mFormat;
return dx2es::GetRedSize(getD3DFormat());
}
bool RenderbufferStorage::isFloatingPoint() const
GLuint RenderbufferStorage::getGreenSize() const
{
return false; // no floating point renderbuffers
return dx2es::GetGreenSize(getD3DFormat());
}
D3DFORMAT RenderbufferStorage::getD3DFormat() const
GLuint RenderbufferStorage::getBlueSize() const
{
return mD3DFormat;
return dx2es::GetBlueSize(getD3DFormat());
}
GLuint RenderbufferStorage::getAlphaSize() const
{
return dx2es::GetAlphaSize(getD3DFormat());
}
GLuint RenderbufferStorage::getDepthSize() const
{
return dx2es::GetDepthSize(getD3DFormat());
}
GLuint RenderbufferStorage::getStencilSize() const
{
return dx2es::GetStencilSize(getD3DFormat());
}
GLsizei RenderbufferStorage::getSamples() const
@ -161,6 +205,11 @@ GLsizei RenderbufferStorage::getSamples() const
return mSamples;
}
D3DFORMAT RenderbufferStorage::getD3DFormat() const
{
return mD3DFormat;
}
unsigned int RenderbufferStorage::getSerial() const
{
return mSerial;
@ -171,7 +220,7 @@ unsigned int RenderbufferStorage::issueSerial()
return mCurrentSerial++;
}
Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget), mTexture(NULL)
{
if (renderTarget)
{
@ -180,25 +229,32 @@ Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(render
D3DSURFACE_DESC description;
renderTarget->GetDesc(&description);
setSize(description.Width, description.Height);
mFormat = dx2es::ConvertBackBufferFormat(description.Format);
mWidth = description.Width;
mHeight = description.Height;
mInternalFormat = dx2es::ConvertBackBufferFormat(description.Format);
mD3DFormat = description.Format;
mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType);
}
}
Colorbuffer::Colorbuffer(const Texture* texture) : mRenderTarget(NULL)
Colorbuffer::Colorbuffer(Texture *texture, GLenum target) : mRenderTarget(NULL), mTexture(texture), mTarget(target)
{
setSize(texture->getWidth(), texture->getHeight());
if (texture)
{
mWidth = texture->getWidth();
mHeight = texture->getHeight();
mInternalFormat = texture->getInternalFormat();
mD3DFormat = texture->getD3DFormat();
mSamples = 0;
mRenderTarget = texture->getRenderTarget(target);
}
}
Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL), mTexture(NULL)
{
IDirect3DDevice9 *device = getDevice();
mRenderTarget = NULL;
D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
@ -224,14 +280,12 @@ Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
ASSERT(SUCCEEDED(result));
}
if (mRenderTarget)
{
setSize(width, height);
mFormat = format;
mWidth = width;
mHeight = height;
mInternalFormat = format;
mD3DFormat = requestedFormat;
mSamples = supportedSamples;
}
}
Colorbuffer::~Colorbuffer()
{
@ -241,65 +295,73 @@ Colorbuffer::~Colorbuffer()
}
}
GLsizei Colorbuffer::getWidth() const
{
if (mTexture)
{
return mTexture->getWidth();
}
return mWidth;
}
GLsizei Colorbuffer::getHeight() const
{
if (mTexture)
{
return mTexture->getHeight();
}
return mHeight;
}
GLenum Colorbuffer::getInternalFormat() const
{
if (mTexture)
{
return mTexture->getInternalFormat();
}
return mInternalFormat;
}
GLenum Colorbuffer::getType() const
{
if (mTexture)
{
return mTexture->getType();
}
return GL_UNSIGNED_BYTE;
}
D3DFORMAT Colorbuffer::getD3DFormat() const
{
if (mTexture)
{
return mTexture->getD3DFormat();
}
return mD3DFormat;
}
bool Colorbuffer::isColorbuffer() const
{
return true;
}
GLuint Colorbuffer::getRedSize()
{
if (getRenderTarget())
{
D3DSURFACE_DESC description;
getRenderTarget()->GetDesc(&description);
return es2dx::GetRedSize(description.Format);
}
return 0;
}
GLuint Colorbuffer::getGreenSize()
{
if (getRenderTarget())
{
D3DSURFACE_DESC description;
getRenderTarget()->GetDesc(&description);
return es2dx::GetGreenSize(description.Format);
}
return 0;
}
GLuint Colorbuffer::getBlueSize()
{
if (getRenderTarget())
{
D3DSURFACE_DESC description;
getRenderTarget()->GetDesc(&description);
return es2dx::GetBlueSize(description.Format);
}
return 0;
}
GLuint Colorbuffer::getAlphaSize()
{
if (getRenderTarget())
{
D3DSURFACE_DESC description;
getRenderTarget()->GetDesc(&description);
return es2dx::GetAlphaSize(description.Format);
}
return 0;
}
IDirect3DSurface9 *Colorbuffer::getRenderTarget()
{
if (mTexture)
{
if (mRenderTarget)
{
mRenderTarget->Release();
}
mRenderTarget = mTexture->getRenderTarget(mTarget);
}
return mRenderTarget;
}
@ -312,9 +374,10 @@ DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepth
D3DSURFACE_DESC description;
depthStencil->GetDesc(&description);
setSize(description.Width, description.Height);
mFormat = dx2es::ConvertDepthStencilFormat(description.Format);
mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
mWidth = description.Width;
mHeight = description.Height;
mInternalFormat = dx2es::ConvertDepthStencilFormat(description.Format);
mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType);
mD3DFormat = description.Format;
}
}
@ -334,6 +397,8 @@ DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
return;
}
if (width > 0 && height > 0)
{
HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
0, FALSE, &mDepthStencil, 0);
@ -345,15 +410,14 @@ DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
}
ASSERT(SUCCEEDED(result));
}
if (mDepthStencil)
{
setSize(width, height);
mFormat = GL_DEPTH24_STENCIL8_OES;
mWidth = width;
mHeight = height;
mInternalFormat = GL_DEPTH24_STENCIL8_OES;
mD3DFormat = D3DFMT_D24S8;
mSamples = supportedSamples;
}
}
DepthStencilbuffer::~DepthStencilbuffer()
{
@ -373,32 +437,6 @@ bool DepthStencilbuffer::isStencilbuffer() const
return true;
}
GLuint DepthStencilbuffer::getDepthSize() const
{
if (mDepthStencil)
{
D3DSURFACE_DESC description;
mDepthStencil->GetDesc(&description);
return es2dx::GetDepthSize(description.Format);
}
return 0;
}
GLuint DepthStencilbuffer::getStencilSize() const
{
if (mDepthStencil)
{
D3DSURFACE_DESC description;
mDepthStencil->GetDesc(&description);
return es2dx::GetStencilSize(description.Format);
}
return 0;
}
IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
{
return mDepthStencil;
@ -408,7 +446,7 @@ Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(d
{
if (depthStencil)
{
mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
// glRenderbufferStorage
}
@ -418,7 +456,7 @@ Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilb
{
if (getDepthStencil())
{
mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
// glRenderbufferStorage
}
@ -442,21 +480,17 @@ Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuff
{
if (depthStencil)
{
mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
// glRenderbufferStorage
}
else
{
mFormat = GL_RGBA4; //default format
}
}
Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
{
if (getDepthStencil())
{
mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
// glRenderbufferStorage
}

Просмотреть файл

@ -40,34 +40,40 @@ class RenderbufferStorage
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
virtual int getWidth() const;
virtual int getHeight() const;
virtual GLenum getFormat() const;
virtual bool isFloatingPoint() const;
D3DFORMAT getD3DFormat() const;
GLsizei getSamples() const;
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
virtual GLenum getInternalFormat() const;
GLuint getRedSize() const;
GLuint getGreenSize() const;
GLuint getBlueSize() const;
GLuint getAlphaSize() const;
GLuint getDepthSize() const;
GLuint getStencilSize() const;
virtual GLsizei getSamples() const;
virtual D3DFORMAT getD3DFormat() const;
unsigned int getSerial() const;
static unsigned int issueSerial();
protected:
void setSize(int width, int height);
GLenum mFormat;
GLsizei mWidth;
GLsizei mHeight;
GLenum mInternalFormat;
D3DFORMAT mD3DFormat;
GLsizei mSamples;
const unsigned int mSerial;
private:
DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
static unsigned int mCurrentSerial;
static unsigned int issueSerial();
int mWidth;
int mHeight;
const unsigned int mSerial;
static unsigned int mCurrentSerial;
};
// Renderbuffer implements the GL renderbuffer object.
// It's only a wrapper for a RenderbufferStorage, but the internal object
// It's only a proxy for a RenderbufferStorage instance; the internal object
// can change whenever glRenderbufferStorage is called.
class Renderbuffer : public RefCountObject
{
@ -83,10 +89,18 @@ class Renderbuffer : public RefCountObject
IDirect3DSurface9 *getRenderTarget();
IDirect3DSurface9 *getDepthStencil();
int getWidth() const;
int getHeight() const;
GLenum getFormat() const;
GLsizei getWidth() const;
GLsizei getHeight() const;
GLenum getInternalFormat() const;
D3DFORMAT getD3DFormat() const;
GLuint getRedSize() const;
GLuint getGreenSize() const;
GLuint getBlueSize() const;
GLuint getAlphaSize() const;
GLuint getDepthSize() const;
GLuint getStencilSize() const;
GLsizei getSamples() const;
unsigned int getSerial() const;
void setStorage(RenderbufferStorage *newStorage);
@ -102,42 +116,42 @@ class Colorbuffer : public RenderbufferStorage
{
public:
explicit Colorbuffer(IDirect3DSurface9 *renderTarget);
explicit Colorbuffer(const Texture* texture);
Colorbuffer(int width, int height, GLenum format, GLsizei samples);
Colorbuffer(Texture *texture, GLenum target);
Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples);
~Colorbuffer();
virtual ~Colorbuffer();
bool isColorbuffer() const;
virtual bool isColorbuffer() const;
GLuint getRedSize();
GLuint getGreenSize();
GLuint getBlueSize();
GLuint getAlphaSize();
virtual IDirect3DSurface9 *getRenderTarget();
IDirect3DSurface9 *getRenderTarget();
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
virtual GLenum getInternalFormat() const;
virtual GLenum getType() const;
protected:
IDirect3DSurface9 *mRenderTarget;
virtual D3DFORMAT getD3DFormat() const;
private:
DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
IDirect3DSurface9 *mRenderTarget;
Texture *mTexture;
GLenum mTarget;
};
class DepthStencilbuffer : public RenderbufferStorage
{
public:
explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil);
DepthStencilbuffer(int width, int height, GLsizei samples);
DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
~DepthStencilbuffer();
virtual bool isDepthbuffer() const;
virtual bool isStencilbuffer() const;
GLuint getDepthSize() const;
GLuint getStencilSize() const;
IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DSurface9 *getDepthStencil();
private:
DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
@ -148,12 +162,12 @@ class Depthbuffer : public DepthStencilbuffer
{
public:
explicit Depthbuffer(IDirect3DSurface9 *depthStencil);
Depthbuffer(int width, int height, GLsizei samples);
Depthbuffer(GLsizei width, GLsizei height, GLsizei samples);
~Depthbuffer();
virtual ~Depthbuffer();
bool isDepthbuffer() const;
bool isStencilbuffer() const;
virtual bool isDepthbuffer() const;
virtual bool isStencilbuffer() const;
private:
DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
@ -163,12 +177,12 @@ class Stencilbuffer : public DepthStencilbuffer
{
public:
explicit Stencilbuffer(IDirect3DSurface9 *depthStencil);
Stencilbuffer(int width, int height, GLsizei samples);
Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
~Stencilbuffer();
virtual ~Stencilbuffer();
bool isDepthbuffer() const;
bool isStencilbuffer() const;
virtual bool isDepthbuffer() const;
virtual bool isStencilbuffer() const;
private:
DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);

Просмотреть файл

@ -66,12 +66,7 @@ void ResourceManager::release()
// Returns an unused buffer name
GLuint ResourceManager::createBuffer()
{
unsigned int handle = 1;
while (mBufferMap.find(handle) != mBufferMap.end())
{
handle++;
}
GLuint handle = mBufferHandleAllocator.allocate();
mBufferMap[handle] = NULL;
@ -81,12 +76,7 @@ GLuint ResourceManager::createBuffer()
// Returns an unused shader/program name
GLuint ResourceManager::createShader(GLenum type)
{
unsigned int handle = 1;
while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
{
handle++;
}
GLuint handle = mProgramShaderHandleAllocator.allocate();
if (type == GL_VERTEX_SHADER)
{
@ -104,12 +94,7 @@ GLuint ResourceManager::createShader(GLenum type)
// Returns an unused program/shader name
GLuint ResourceManager::createProgram()
{
unsigned int handle = 1;
while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
{
handle++;
}
GLuint handle = mProgramShaderHandleAllocator.allocate();
mProgramMap[handle] = new Program(this, handle);
@ -119,12 +104,7 @@ GLuint ResourceManager::createProgram()
// Returns an unused texture name
GLuint ResourceManager::createTexture()
{
unsigned int handle = 1;
while (mTextureMap.find(handle) != mTextureMap.end())
{
handle++;
}
GLuint handle = mTextureHandleAllocator.allocate();
mTextureMap[handle] = NULL;
@ -134,12 +114,7 @@ GLuint ResourceManager::createTexture()
// Returns an unused renderbuffer name
GLuint ResourceManager::createRenderbuffer()
{
unsigned int handle = 1;
while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
{
handle++;
}
GLuint handle = mRenderbufferHandleAllocator.allocate();
mRenderbufferMap[handle] = NULL;
@ -152,6 +127,7 @@ void ResourceManager::deleteBuffer(GLuint buffer)
if (bufferObject != mBufferMap.end())
{
mBufferHandleAllocator.release(bufferObject->first);
if (bufferObject->second) bufferObject->second->release();
mBufferMap.erase(bufferObject);
}
@ -165,6 +141,7 @@ void ResourceManager::deleteShader(GLuint shader)
{
if (shaderObject->second->getRefCount() == 0)
{
mProgramShaderHandleAllocator.release(shaderObject->first);
delete shaderObject->second;
mShaderMap.erase(shaderObject);
}
@ -183,6 +160,7 @@ void ResourceManager::deleteProgram(GLuint program)
{
if (programObject->second->getRefCount() == 0)
{
mProgramShaderHandleAllocator.release(programObject->first);
delete programObject->second;
mProgramMap.erase(programObject);
}
@ -199,6 +177,7 @@ void ResourceManager::deleteTexture(GLuint texture)
if (textureObject != mTextureMap.end())
{
mTextureHandleAllocator.release(textureObject->first);
if (textureObject->second) textureObject->second->release();
mTextureMap.erase(textureObject);
}
@ -210,6 +189,7 @@ void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
if (renderbufferObject != mRenderbufferMap.end())
{
mRenderbufferHandleAllocator.release(renderbufferObject->first);
if (renderbufferObject->second) renderbufferObject->second->release();
mRenderbufferMap.erase(renderbufferObject);
}
@ -302,17 +282,17 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer)
}
}
void ResourceManager::checkTextureAllocation(GLuint texture, SamplerType type)
void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
{
if (!getTexture(texture) && texture != 0)
{
Texture *textureObject;
if (type == SAMPLER_2D)
if (type == TEXTURE_2D)
{
textureObject = new Texture2D(texture);
}
else if (type == SAMPLER_CUBE)
else if (type == TEXTURE_CUBE)
{
textureObject = new TextureCubeMap(texture);
}

Просмотреть файл

@ -13,9 +13,10 @@
#define GL_APICALL
#include <GLES2/gl2.h>
#include <map>
#include <hash_map>
#include "common/angleutils.h"
#include "libGLESv2/HandleAllocator.h"
namespace gl
{
@ -25,12 +26,19 @@ class Program;
class Texture;
class Renderbuffer;
enum TextureType
{
TEXTURE_2D,
TEXTURE_CUBE,
TEXTURE_TYPE_COUNT,
TEXTURE_UNKNOWN
};
enum SamplerType
{
SAMPLER_2D,
SAMPLER_CUBE,
SAMPLER_TYPE_COUNT
SAMPLER_PIXEL,
SAMPLER_VERTEX
};
class ResourceManager
@ -63,7 +71,7 @@ class ResourceManager
void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
void checkBufferAllocation(unsigned int buffer);
void checkTextureAllocation(GLuint texture, SamplerType type);
void checkTextureAllocation(GLuint texture, TextureType type);
void checkRenderbufferAllocation(GLuint renderbuffer);
private:
@ -71,20 +79,24 @@ class ResourceManager
std::size_t mRefCount;
typedef std::map<GLuint, Buffer*> BufferMap;
typedef stdext::hash_map<GLuint, Buffer*> BufferMap;
BufferMap mBufferMap;
HandleAllocator mBufferHandleAllocator;
typedef std::map<GLuint, Shader*> ShaderMap;
typedef stdext::hash_map<GLuint, Shader*> ShaderMap;
ShaderMap mShaderMap;
typedef std::map<GLuint, Program*> ProgramMap;
typedef stdext::hash_map<GLuint, Program*> ProgramMap;
ProgramMap mProgramMap;
HandleAllocator mProgramShaderHandleAllocator;
typedef std::map<GLuint, Texture*> TextureMap;
typedef stdext::hash_map<GLuint, Texture*> TextureMap;
TextureMap mTextureMap;
HandleAllocator mTextureHandleAllocator;
typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
typedef stdext::hash_map<GLuint, Renderbuffer*> RenderbufferMap;
RenderbufferMap mRenderbufferMap;
HandleAllocator mRenderbufferHandleAllocator;
};
}

Просмотреть файл

@ -41,8 +41,8 @@ Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mReso
resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
resources.MaxVaryingVectors = context->getMaximumVaryingVectors();
resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
resources.MaxVertexTextureImageUnits = context->getMaximumVertexTextureImageUnits();
resources.MaxCombinedTextureImageUnits = context->getMaximumCombinedTextureImageUnits();
resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors();
resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;

Просмотреть файл

@ -127,8 +127,8 @@ class VertexShader : public Shader
~VertexShader();
GLenum getType();
void compile();
virtual GLenum getType();
virtual void compile();
int getSemanticIndex(const std::string &attributeName);
private:
@ -146,8 +146,8 @@ class FragmentShader : public Shader
~FragmentShader();
GLenum getType();
void compile();
virtual GLenum getType();
virtual void compile();
private:
DISALLOW_COPY_AND_ASSIGN(FragmentShader);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -22,6 +22,11 @@
#include "libGLESv2/utilities.h"
#include "common/debug.h"
namespace egl
{
class Surface;
}
namespace gl
{
class Blit;
@ -57,49 +62,30 @@ class Texture : public RefCountObject
GLenum getWrapS() const;
GLenum getWrapT() const;
GLuint getWidth() const;
GLuint getHeight() const;
virtual GLsizei getWidth() const = 0;
virtual GLsizei getHeight() const = 0;
virtual GLenum getInternalFormat() const = 0;
virtual GLenum getType() const = 0;
virtual D3DFORMAT getD3DFormat() const = 0;
virtual GLenum getFormat() const = 0;
virtual bool isComplete() const = 0;
virtual bool isCompressed() const = 0;
bool isFloatingPoint() const;
bool isRenderableFormat() const;
D3DFORMAT getD3DFormat() const;
IDirect3DBaseTexture9 *getTexture();
virtual Renderbuffer *getColorbuffer(GLenum target) = 0;
virtual Renderbuffer *getRenderbuffer(GLenum target) = 0;
virtual void generateMipmaps() = 0;
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;
bool isDirty() const;
bool isDirtyParameter() const;
bool isDirtyImage() const;
void resetDirty();
unsigned int getSerial() const;
static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
protected:
class TextureColorbufferProxy;
friend class TextureColorbufferProxy;
class TextureColorbufferProxy : public Colorbuffer
{
public:
TextureColorbufferProxy(Texture *texture, GLenum target);
// target is a 2D-like texture target (GL_TEXTURE_2D or one of the cube face targets)
virtual void addRef() const;
virtual void release() const;
virtual IDirect3DSurface9 *getRenderTarget();
virtual int getWidth() const;
virtual int getHeight() const;
virtual GLenum getFormat() const;
virtual bool isFloatingPoint() const;
private:
Texture *mTexture;
GLenum mTarget;
};
friend class Colorbuffer;
// Helper structure representing a single image layer
struct Image
@ -107,55 +93,49 @@ class Texture : public RefCountObject
Image();
~Image();
bool isRenderable() const;
D3DFORMAT getD3DFormat() const;
GLsizei width;
GLsizei height;
GLenum format;
GLenum type;
bool dirty;
IDirect3DSurface9 *surface;
};
static D3DFORMAT selectFormat(GLenum format, GLenum type);
void setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
void setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img);
bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img);
void copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
void needRenderTarget();
void setImage(GLint unpackAlignment, const void *pixels, Image *image);
bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image);
void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image);
void copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
GLint creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const;
GLint creationLevels(GLsizei size, GLint maxlevel) const;
// The pointer returned is weak and it is assumed the derived class will keep a strong pointer until the next createTexture() call.
virtual IDirect3DBaseTexture9 *createTexture() = 0;
virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
virtual void createTexture() = 0;
virtual void updateTexture() = 0;
virtual IDirect3DBaseTexture9 *convertToRenderTarget() = 0;
virtual void convertToRenderTarget() = 0;
virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0;
virtual bool dirtyImageData() const = 0;
void dropTexture();
void pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable);
void createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img);
void createSurface(Image *image);
Blit *getBlitter();
int levelCount() const;
bool isRenderable() const;
unsigned int mWidth;
unsigned int mHeight;
GLenum mMinFilter;
GLenum mMagFilter;
GLenum mWrapS;
GLenum mWrapT;
GLenum mType;
bool mDirtyParameter;
bool mDirtyMetaData;
bool mDirtyImage;
bool mIsRenderable;
private:
DISALLOW_COPY_AND_ASSIGN(Texture);
@ -189,6 +169,8 @@ class Texture : public RefCountObject
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBAUByteImageDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
@ -204,10 +186,11 @@ class Texture : public RefCountObject
void loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const;
IDirect3DBaseTexture9 *mBaseTexture; // This is a weak pointer. The derived class is assumed to own a strong pointer.
static unsigned int issueSerial();
bool mDirty;
bool mIsRenderable;
const unsigned int mSerial;
static unsigned int mCurrentSerial;
};
class Texture2D : public Texture
@ -217,39 +200,46 @@ class Texture2D : public Texture
~Texture2D();
GLenum getTarget() const;
GLenum getFormat() const;
virtual GLenum getTarget() const;
void setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
virtual GLenum getInternalFormat() const;
virtual GLenum getType() const;
virtual D3DFORMAT getD3DFormat() const;
void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
bool isComplete() const;
bool isCompressed() const;
virtual bool isComplete() const;
virtual bool isCompressed() const;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
virtual void generateMipmaps();
virtual Renderbuffer *getColorbuffer(GLenum target);
virtual Renderbuffer *getRenderbuffer(GLenum target);
private:
DISALLOW_COPY_AND_ASSIGN(Texture2D);
virtual IDirect3DBaseTexture9 *createTexture();
virtual IDirect3DBaseTexture9 *getBaseTexture() const;
virtual void createTexture();
virtual void updateTexture();
virtual IDirect3DBaseTexture9 *convertToRenderTarget();
virtual void convertToRenderTarget();
virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
virtual bool dirtyImageData() const;
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type);
void redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool force);
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
IDirect3DTexture9 *mTexture;
egl::Surface *mSurface;
BindingPointer<Renderbuffer> mColorbufferProxy;
};
@ -261,40 +251,44 @@ class TextureCubeMap : public Texture
~TextureCubeMap();
GLenum getTarget() const;
GLenum getFormat() const;
virtual GLenum getTarget() const;
void setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
virtual GLenum getInternalFormat() const;
virtual GLenum getType() const;
virtual D3DFORMAT getD3DFormat() const;
void setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
bool isComplete() const;
bool isCompressed() const;
virtual bool isComplete() const;
virtual bool isCompressed() const;
virtual void generateMipmaps();
virtual Renderbuffer *getColorbuffer(GLenum target);
virtual Renderbuffer *getRenderbuffer(GLenum target);
private:
DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
virtual IDirect3DBaseTexture9 *createTexture();
virtual IDirect3DBaseTexture9 *getBaseTexture() const;
virtual void createTexture();
virtual void updateTexture();
virtual IDirect3DBaseTexture9 *convertToRenderTarget();
virtual void convertToRenderTarget();
virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
virtual bool dirtyImageData() const;
// face is one of the GL_TEXTURE_CUBE_MAP_* enumerants.
// Returns NULL if the call underlying Direct3D call fails.
IDirect3DSurface9 *getCubeMapSurface(GLenum face, unsigned int level);
@ -303,9 +297,9 @@ class TextureCubeMap : public Texture
bool isCubeComplete() const;
void setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width);
void redefineTexture(int faceIndex, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];

Просмотреть файл

@ -0,0 +1,733 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VertexDataManager.h: Defines the VertexDataManager, a class that
// runs the Buffer translation process.
#include "libGLESv2/VertexDataManager.h"
#include "common/debug.h"
#include "libGLESv2/Buffer.h"
#include "libGLESv2/Program.h"
#include "libGLESv2/main.h"
#include "libGLESv2/vertexconversion.h"
#include "libGLESv2/IndexDataManager.h"
namespace
{
enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
}
namespace gl
{
VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device)
{
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
mDirtyCurrentValue[i] = true;
mCurrentValueBuffer[i] = NULL;
}
const D3DCAPS9 &caps = context->getDeviceCaps();
checkVertexCaps(caps.DeclTypes);
mStreamingBuffer = new StreamingVertexBuffer(mDevice, INITIAL_STREAM_BUFFER_SIZE);
if (!mStreamingBuffer)
{
ERR("Failed to allocate the streaming vertex buffer.");
}
}
VertexDataManager::~VertexDataManager()
{
delete mStreamingBuffer;
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
delete mCurrentValueBuffer[i];
}
}
UINT VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute)
{
Buffer *buffer = attribute.mBoundBuffer.get();
int inputStride = attribute.stride();
int elementSize = attribute.typeSize();
const FormatConverter &converter = formatConverter(attribute);
UINT streamOffset = 0;
void *output = NULL;
if (vertexBuffer)
{
output = vertexBuffer->map(attribute, spaceRequired(attribute, count), &streamOffset);
}
if (output == NULL)
{
ERR("Failed to map vertex buffer.");
return -1;
}
const char *input = NULL;
if (buffer)
{
int offset = attribute.mOffset;
input = static_cast<const char*>(buffer->data()) + offset;
}
else
{
input = static_cast<const char*>(attribute.mPointer);
}
input += inputStride * start;
if (converter.identity && inputStride == elementSize)
{
memcpy(output, input, count * inputStride);
}
else
{
converter.convertArray(input, inputStride, count, output);
}
vertexBuffer->unmap();
return streamOffset;
}
GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated)
{
if (!mStreamingBuffer)
{
return GL_OUT_OF_MEMORY;
}
const VertexAttributeArray &attribs = mContext->getVertexAttributes();
Program *program = mContext->getCurrentProgram();
for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{
translated[attributeIndex].active = (program->getSemanticIndex(attributeIndex) != -1);
}
// Determine the required storage size per used buffer, and invalidate static buffers that don't contain matching attributes
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (translated[i].active && attribs[i].mArrayEnabled)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
if (staticBuffer)
{
if (staticBuffer->size() == 0)
{
int totalCount = buffer->size() / attribs[i].stride();
staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount));
}
else if (staticBuffer->lookupAttribute(attribs[i]) == -1)
{
// This static buffer doesn't have matching attributes, so fall back to using the streaming buffer
mStreamingBuffer->addRequiredSpaceFor(staticBuffer);
buffer->invalidateStaticData();
mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count));
}
}
else
{
mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count));
}
}
}
// Reserve the required space per used buffer
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (translated[i].active && attribs[i].mArrayEnabled)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer;
if (vertexBuffer)
{
vertexBuffer->reserveRequiredSpace();
}
}
}
// Perform the vertex data translations
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (translated[i].active)
{
if (attribs[i].mArrayEnabled)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
if (!buffer && attribs[i].mPointer == NULL)
{
// This is an application error that would normally result in a crash, but we catch it and return an error
ERR("An enabled vertex array has no buffer and no pointer.");
return GL_INVALID_OPERATION;
}
const FormatConverter &converter = formatConverter(attribs[i]);
StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast<ArrayVertexBuffer*>(mStreamingBuffer);
UINT streamOffset = -1;
if (staticBuffer)
{
streamOffset = staticBuffer->lookupAttribute(attribs[i]);
if (streamOffset == -1)
{
// Convert the entire buffer
int totalCount = buffer->size() / attribs[i].stride();
int startIndex = attribs[i].mOffset / attribs[i].stride();
streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i]);
}
if (streamOffset != -1)
{
streamOffset += (start + attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize;
}
}
else
{
streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]);
}
if (streamOffset == -1)
{
return GL_OUT_OF_MEMORY;
}
translated[i].vertexBuffer = vertexBuffer->getBuffer();
translated[i].type = converter.d3dDeclType;
translated[i].stride = converter.outputElementSize;
translated[i].offset = streamOffset;
}
else
{
if (mDirtyCurrentValue[i])
{
delete mCurrentValueBuffer[i];
mCurrentValueBuffer[i] = new ConstantVertexBuffer(mDevice, attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]);
mDirtyCurrentValue[i] = false;
}
translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer();
translated[i].type = D3DDECLTYPE_FLOAT4;
translated[i].stride = 0;
translated[i].offset = 0;
}
}
}
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (translated[i].active && attribs[i].mArrayEnabled)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
if (buffer)
{
buffer->promoteStaticUsage(count * attribs[i].typeSize());
}
}
}
return GL_NO_ERROR;
}
std::size_t VertexDataManager::spaceRequired(const VertexAttribute &attrib, std::size_t count) const
{
return formatConverter(attrib).outputElementSize * count;
}
// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
//
// BYTE SHORT (Cast)
// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast)
// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize)
// SHORT SHORT (Identity)
// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize)
// UNSIGNED_SHORT FLOAT (Cast)
// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize)
// FIXED (not in WebGL) FLOAT (FixedToFloat)
// FLOAT FLOAT (Identity)
// GLToCType maps from GL type (as GLenum) to the C typedef.
template <GLenum GLType> struct GLToCType { };
template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
enum D3DVertexType
{
D3DVT_FLOAT,
D3DVT_SHORT,
D3DVT_SHORT_NORM,
D3DVT_UBYTE,
D3DVT_UBYTE_NORM,
D3DVT_USHORT_NORM
};
// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
template <unsigned int D3DType> struct D3DToCType { };
template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
template <unsigned int type, int size>
struct WidenRule
{
};
template <int size> struct WidenRule<D3DVT_FLOAT, size> : gl::NoWiden<size> { };
template <int size> struct WidenRule<D3DVT_SHORT, size> : gl::WidenToEven<size> { };
template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : gl::WidenToEven<size> { };
template <int size> struct WidenRule<D3DVT_UBYTE, size> : gl::WidenToFour<size> { };
template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : gl::WidenToFour<size> { };
template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : gl::WidenToEven<size> { };
// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
template <unsigned int d3dtype, int size>
struct VertexTypeFlags
{
};
template <unsigned int capflag, unsigned int declflag>
struct VertexTypeFlagsHelper
{
enum { capflag = capflag };
enum { declflag = declflag };
};
template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
template <GLenum GLtype, bool normalized>
struct VertexTypeMapping
{
};
template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
struct VertexTypeMappingBase
{
enum { preferred = Preferred };
enum { fallback = Fallback };
};
template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast
template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize
template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast
template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize
template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity
template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast
template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat
template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity
// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
// The conversion rules themselves are defined in vertexconversion.h.
// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
template <GLenum fromType, bool normalized, unsigned int toType>
struct ConversionRule : gl::Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type>
{
};
// All conversions from normalized types to float use the Normalize operator.
template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : gl::Normalize<typename GLToCType<fromType>::type> { };
// Use a full specialisation for this so that it preferentially matches ahead of the generic normalize-to-float rules.
template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : gl::FixedToFloat<GLuint, 16> { };
template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : gl::FixedToFloat<GLuint, 16> { };
// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
// whether it is normalized or not.
template <class T, bool normalized>
struct DefaultVertexValuesStage2
{
};
template <class T> struct DefaultVertexValuesStage2<T, true> : gl::NormalizedDefaultValues<T> { };
template <class T> struct DefaultVertexValuesStage2<T, false> : gl::SimpleDefaultValues<T> { };
// Work out the default value rule for a D3D type (expressed as the C type) and
template <class T, bool normalized>
struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized>
{
};
template <bool normalized> struct DefaultVertexValues<float, normalized> : gl::SimpleDefaultValues<float> { };
// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
// The fallback conversion produces an output that all D3D9 devices must support.
template <class T> struct UsePreferred { enum { type = T::preferred }; };
template <class T> struct UseFallback { enum { type = T::fallback }; };
// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
struct Converter
: gl::VertexDataConverter<typename GLToCType<fromType>::type,
WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
ConversionRule<fromType,
normalized,
PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
{
private:
enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
public:
enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
};
// Initialise a TranslationInfo
#define TRANSLATION(type, norm, size, preferred) \
{ \
Converter<type, norm, size, preferred>::identity, \
Converter<type, norm, size, preferred>::finalSize, \
Converter<type, norm, size, preferred>::convertArray, \
static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \
}
#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \
{ \
Converter<type, norm, size, UsePreferred>::capflag, \
TRANSLATION(type, norm, size, UsePreferred), \
TRANSLATION(type, norm, size, UseFallback) \
}
#define TRANSLATIONS_FOR_TYPE(type) \
{ \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \
}
const VertexDataManager::TranslationDescription VertexDataManager::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
{
TRANSLATIONS_FOR_TYPE(GL_BYTE),
TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
TRANSLATIONS_FOR_TYPE(GL_SHORT),
TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
TRANSLATIONS_FOR_TYPE(GL_FIXED),
TRANSLATIONS_FOR_TYPE(GL_FLOAT)
};
void VertexDataManager::checkVertexCaps(DWORD declTypes)
{
for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
{
for (unsigned int j = 0; j < 2; j++)
{
for (unsigned int k = 0; k < 4; k++)
{
if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
{
mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
}
else
{
mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
}
}
}
}
}
// This is used to index mAttributeTypes and mPossibleTranslations.
unsigned int VertexDataManager::typeIndex(GLenum type) const
{
switch (type)
{
case GL_BYTE: return 0;
case GL_UNSIGNED_BYTE: return 1;
case GL_SHORT: return 2;
case GL_UNSIGNED_SHORT: return 3;
case GL_FIXED: return 4;
case GL_FLOAT: return 5;
default: UNREACHABLE(); return 5;
}
}
VertexBuffer::VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : mDevice(device), mVertexBuffer(NULL)
{
if (size > 0)
{
D3DPOOL pool = getDisplay()->getBufferPool(usageFlags);
HRESULT result = device->CreateVertexBuffer(size, usageFlags, 0, pool, &mVertexBuffer, NULL);
if (FAILED(result))
{
ERR("Out of memory allocating a vertex buffer of size %lu.", size);
}
}
}
VertexBuffer::~VertexBuffer()
{
if (mVertexBuffer)
{
mVertexBuffer->Release();
}
}
void VertexBuffer::unmap()
{
if (mVertexBuffer)
{
mVertexBuffer->Unlock();
}
}
IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const
{
return mVertexBuffer;
}
ConstantVertexBuffer::ConstantVertexBuffer(IDirect3DDevice9 *device, float x, float y, float z, float w) : VertexBuffer(device, 4 * sizeof(float), D3DUSAGE_WRITEONLY)
{
void *buffer = NULL;
if (mVertexBuffer)
{
HRESULT result = mVertexBuffer->Lock(0, 0, &buffer, 0);
if (FAILED(result))
{
ERR("Lock failed with error 0x%08x", result);
}
}
if (buffer)
{
float *vector = (float*)buffer;
vector[0] = x;
vector[1] = y;
vector[2] = z;
vector[3] = w;
mVertexBuffer->Unlock();
}
}
ConstantVertexBuffer::~ConstantVertexBuffer()
{
}
ArrayVertexBuffer::ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : VertexBuffer(device, size, usageFlags)
{
mBufferSize = size;
mWritePosition = 0;
mRequiredSpace = 0;
}
ArrayVertexBuffer::~ArrayVertexBuffer()
{
}
void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace)
{
mRequiredSpace += requiredSpace;
}
void ArrayVertexBuffer::addRequiredSpaceFor(ArrayVertexBuffer *buffer)
{
mRequiredSpace += buffer->mRequiredSpace;
}
StreamingVertexBuffer::StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize) : ArrayVertexBuffer(device, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)
{
}
StreamingVertexBuffer::~StreamingVertexBuffer()
{
}
void *StreamingVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset)
{
void *mapPtr = NULL;
if (mVertexBuffer)
{
HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
if (FAILED(result))
{
ERR("Lock failed with error 0x%08x", result);
return NULL;
}
*offset = mWritePosition;
mWritePosition += requiredSpace;
}
return mapPtr;
}
void StreamingVertexBuffer::reserveRequiredSpace()
{
if (mRequiredSpace > mBufferSize)
{
if (mVertexBuffer)
{
mVertexBuffer->Release();
mVertexBuffer = NULL;
}
mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2); // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations.
D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
HRESULT result = mDevice->CreateVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL);
if (FAILED(result))
{
ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
}
mWritePosition = 0;
}
else if (mWritePosition + mRequiredSpace > mBufferSize) // Recycle
{
if (mVertexBuffer)
{
void *dummy;
mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
mVertexBuffer->Unlock();
}
mWritePosition = 0;
}
mRequiredSpace = 0;
}
StaticVertexBuffer::StaticVertexBuffer(IDirect3DDevice9 *device) : ArrayVertexBuffer(device, 0, D3DUSAGE_WRITEONLY)
{
}
StaticVertexBuffer::~StaticVertexBuffer()
{
}
void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, UINT *streamOffset)
{
void *mapPtr = NULL;
if (mVertexBuffer)
{
HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0);
if (FAILED(result))
{
ERR("Lock failed with error 0x%08x", result);
return NULL;
}
int attributeOffset = attribute.mOffset % attribute.stride();
VertexElement element = {attribute.mType, attribute.mSize, attribute.mNormalized, attributeOffset, mWritePosition};
mCache.push_back(element);
*streamOffset = mWritePosition;
mWritePosition += requiredSpace;
}
return mapPtr;
}
void StaticVertexBuffer::reserveRequiredSpace()
{
if (!mVertexBuffer && mBufferSize == 0)
{
D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY);
HRESULT result = mDevice->CreateVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL);
if (FAILED(result))
{
ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace);
}
mBufferSize = mRequiredSpace;
}
else if (mVertexBuffer && mBufferSize >= mRequiredSpace)
{
// Already allocated
}
else UNREACHABLE(); // Static vertex buffers can't be resized
mRequiredSpace = 0;
}
UINT StaticVertexBuffer::lookupAttribute(const VertexAttribute &attribute)
{
for (unsigned int element = 0; element < mCache.size(); element++)
{
if (mCache[element].type == attribute.mType && mCache[element].size == attribute.mSize && mCache[element].normalized == attribute.mNormalized)
{
if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
{
return mCache[element].streamOffset;
}
}
}
return -1;
}
const VertexDataManager::FormatConverter &VertexDataManager::formatConverter(const VertexAttribute &attribute) const
{
return mAttributeTypes[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
}
}

Просмотреть файл

@ -0,0 +1,168 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VertexDataManager.h: Defines the VertexDataManager, a class that
// runs the Buffer translation process.
#ifndef LIBGLESV2_VERTEXDATAMANAGER_H_
#define LIBGLESV2_VERTEXDATAMANAGER_H_
#include <vector>
#include <cstddef>
#define GL_APICALL
#include <GLES2/gl2.h>
#include "libGLESv2/Context.h"
namespace gl
{
struct TranslatedAttribute
{
bool active;
D3DDECLTYPE type;
UINT offset;
UINT stride; // 0 means not to advance the read pointer at all
IDirect3DVertexBuffer9 *vertexBuffer;
};
class VertexBuffer
{
public:
VertexBuffer(IDirect3DDevice9 *device, UINT size, DWORD usageFlags);
virtual ~VertexBuffer();
void unmap();
IDirect3DVertexBuffer9 *getBuffer() const;
protected:
IDirect3DDevice9 *const mDevice;
IDirect3DVertexBuffer9 *mVertexBuffer;
private:
DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
};
class ConstantVertexBuffer : public VertexBuffer
{
public:
ConstantVertexBuffer(IDirect3DDevice9 *device, float x, float y, float z, float w);
~ConstantVertexBuffer();
};
class ArrayVertexBuffer : public VertexBuffer
{
public:
ArrayVertexBuffer(IDirect3DDevice9 *device, UINT size, DWORD usageFlags);
~ArrayVertexBuffer();
UINT size() const { return mBufferSize; }
virtual void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset) = 0;
virtual void reserveRequiredSpace() = 0;
void addRequiredSpace(UINT requiredSpace);
void addRequiredSpaceFor(ArrayVertexBuffer *buffer);
protected:
UINT mBufferSize;
UINT mWritePosition;
UINT mRequiredSpace;
};
class StreamingVertexBuffer : public ArrayVertexBuffer
{
public:
StreamingVertexBuffer(IDirect3DDevice9 *device, UINT initialSize);
~StreamingVertexBuffer();
void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset);
void reserveRequiredSpace();
};
class StaticVertexBuffer : public ArrayVertexBuffer
{
public:
explicit StaticVertexBuffer(IDirect3DDevice9 *device);
~StaticVertexBuffer();
void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset);
void reserveRequiredSpace();
UINT lookupAttribute(const VertexAttribute &attribute); // Returns the offset into the vertex buffer, or -1 if not found
private:
struct VertexElement
{
GLenum type;
GLint size;
bool normalized;
int attributeOffset;
UINT streamOffset;
};
std::vector<VertexElement> mCache;
};
class VertexDataManager
{
public:
VertexDataManager(Context *context, IDirect3DDevice9 *backend);
virtual ~VertexDataManager();
void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; }
GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs);
private:
DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
UINT spaceRequired(const VertexAttribute &attrib, std::size_t count) const;
UINT writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute);
Context *const mContext;
IDirect3DDevice9 *const mDevice;
StreamingVertexBuffer *mStreamingBuffer;
bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS];
ConstantVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS];
// Attribute format conversion
struct FormatConverter
{
bool identity;
std::size_t outputElementSize;
void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
D3DDECLTYPE d3dDeclType;
};
enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
struct TranslationDescription
{
DWORD capsFlag;
FormatConverter preferredConversion;
FormatConverter fallbackConversion;
};
// This table is used to generate mAttributeTypes.
static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
void checkVertexCaps(DWORD declTypes);
unsigned int typeIndex(GLenum type) const;
const FormatConverter &formatConverter(const VertexAttribute &attribute) const;
};
}
#endif // LIBGLESV2_VERTEXDATAMANAGER_H_

Просмотреть файл

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@ -37,15 +37,15 @@ void __stdcall glActiveTexture(GLenum texture)
try
{
if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + gl::MAX_TEXTURE_IMAGE_UNITS - 1)
{
return error(GL_INVALID_ENUM);
}
gl::Context *context = gl::getContext();
if (context)
{
if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1)
{
return error(GL_INVALID_ENUM);
}
context->setActiveSampler(texture - GL_TEXTURE0);
}
}
@ -1044,7 +1044,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
}
gl::Colorbuffer *source = framebuffer->getColorbuffer();
GLenum colorbufferFormat = source->getFormat();
GLenum colorbufferFormat = source->getInternalFormat();
// [OpenGL ES 2.0.24] table 3.9
switch (internalformat)
@ -1178,7 +1178,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
}
gl::Colorbuffer *source = framebuffer->getColorbuffer();
GLenum colorbufferFormat = source->getFormat();
GLenum colorbufferFormat = source->getInternalFormat();
gl::Texture *texture = NULL;
if (target == GL_TEXTURE_2D)
@ -1196,7 +1196,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
return error(GL_INVALID_OPERATION);
}
GLenum textureFormat = texture->getFormat();
GLenum textureFormat = texture->getInternalFormat();
// [OpenGL ES 2.0.24] table 3.9
switch (textureFormat)
@ -2954,86 +2954,24 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint*
switch (pname)
{
case GL_RENDERBUFFER_WIDTH:
*params = renderbuffer->getWidth();
break;
case GL_RENDERBUFFER_HEIGHT:
*params = renderbuffer->getHeight();
break;
case GL_RENDERBUFFER_INTERNAL_FORMAT:
*params = renderbuffer->getFormat();
break;
case GL_RENDERBUFFER_RED_SIZE:
if (renderbuffer->isColorbuffer())
{
*params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getRedSize();
}
else
{
*params = 0;
}
break;
case GL_RENDERBUFFER_GREEN_SIZE:
if (renderbuffer->isColorbuffer())
{
*params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getGreenSize();
}
else
{
*params = 0;
}
break;
case GL_RENDERBUFFER_BLUE_SIZE:
if (renderbuffer->isColorbuffer())
{
*params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getBlueSize();
}
else
{
*params = 0;
}
break;
case GL_RENDERBUFFER_ALPHA_SIZE:
if (renderbuffer->isColorbuffer())
{
*params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getAlphaSize();
}
else
{
*params = 0;
}
break;
case GL_RENDERBUFFER_DEPTH_SIZE:
if (renderbuffer->isDepthbuffer())
{
*params = static_cast<gl::Depthbuffer*>(renderbuffer->getStorage())->getDepthSize();
}
else
{
*params = 0;
}
break;
case GL_RENDERBUFFER_STENCIL_SIZE:
if (renderbuffer->isStencilbuffer())
{
*params = static_cast<gl::Stencilbuffer*>(renderbuffer->getStorage())->getStencilSize();
}
else
{
*params = 0;
}
break;
case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
case GL_RENDERBUFFER_SAMPLES_ANGLE:
{
if (context->getMaxSupportedSamples() != 0)
{
*params = renderbuffer->getStorage()->getSamples();
*params = renderbuffer->getSamples();
}
else
{
return error(GL_INVALID_ENUM);
}
}
break;
default:
return error(GL_INVALID_ENUM);
@ -4474,7 +4412,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_OPERATION);
}
switch (internalformat)
switch (format)
{
case GL_ALPHA:
case GL_LUMINANCE:
@ -4569,8 +4507,8 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_ENUM);
}
if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
{
if (context->supportsCompressedTextures())
{
@ -4606,7 +4544,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_OPERATION);
}
texture->setImage(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
}
else
{
@ -4620,22 +4558,22 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
switch (target)
{
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
texture->setImagePosX(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
texture->setImagePosX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
texture->setImageNegX(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
texture->setImageNegX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
texture->setImagePosY(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
texture->setImagePosY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
texture->setImageNegY(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
texture->setImageNegY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
texture->setImagePosZ(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
texture->setImagePosZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
texture->setImageNegZ(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
texture->setImageNegZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
default: UNREACHABLE();
}
@ -4797,7 +4735,7 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
return error(GL_INVALID_OPERATION);
}
if (format != texture->getFormat())
if (format != texture->getInternalFormat())
{
return error(GL_INVALID_OPERATION);
}
@ -4813,16 +4751,6 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
return error(GL_INVALID_OPERATION);
}
if (texture->isCompressed())
{
return error(GL_INVALID_OPERATION);
}
if (format != texture->getFormat())
{
return error(GL_INVALID_OPERATION);
}
texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
}
else
@ -5763,4 +5691,29 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *
return NULL;
}
void __stdcall glBindTexImage(egl::Surface *surface)
{
EVENT("(egl::Surface* surface = 0x%0.8p)",
surface);
try
{
gl::Context *context = gl::getContext();
if (context)
{
gl::Texture2D *textureObject = context->getTexture2D();
if (textureObject)
{
textureObject->bindTexImage(surface);
}
}
}
catch(std::bad_alloc&)
{
return error(GL_OUT_OF_MEMORY);
}
}
}

Просмотреть файл

@ -161,3 +161,4 @@ EXPORTS
glMakeCurrent @146 NONAME
glGetCurrentContext @147 NONAME
glGetProcAddress @148 NONAME
glBindTexImage @158 NONAME

Просмотреть файл

@ -9,6 +9,12 @@
#ifndef LIBGLESV2_MATHUTIL_H_
#define LIBGLESV2_MATHUTIL_H_
#if _MSC_VER <= 1400
#define _interlockedbittestandreset _interlockedbittestandreset_NAME_CHANGED_TO_AVOID_MSVS2005_ERROR
#define _interlockedbittestandset _interlockedbittestandset_NAME_CHANGED_TO_AVOID_MSVS2005_ERROR
#endif
#include <intrin.h>
#include <math.h>
#include <windows.h>
@ -88,6 +94,31 @@ inline GLenum adjustWinding(GLenum winding)
ASSERT(winding == GL_CW || winding == GL_CCW);
return winding == GL_CW ? GL_CCW : GL_CW;
}
inline bool supportsSSE2()
{
static bool checked = false;
static bool supports = false;
if (checked)
{
return supports;
}
int info[4];
__cpuid(info, 0);
if (info[0] >= 1)
{
__cpuid(info, 1);
supports = (info[3] >> 26) & 1;
}
checked = true;
return supports;
}
}
#endif // LIBGLESV2_MATHUTIL_H_

Просмотреть файл

@ -608,137 +608,6 @@ void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DT
}
}
unsigned int GetStencilSize(D3DFORMAT stencilFormat)
{
switch(stencilFormat)
{
case D3DFMT_D24FS8:
case D3DFMT_D24S8:
return 8;
case D3DFMT_D24X4S4:
return 4;
case D3DFMT_D15S1:
return 1;
case D3DFMT_D16_LOCKABLE:
case D3DFMT_D32:
case D3DFMT_D24X8:
case D3DFMT_D32F_LOCKABLE:
case D3DFMT_D16:
return 0;
// case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
// case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
default: UNREACHABLE();
}
return 0;
}
unsigned int GetAlphaSize(D3DFORMAT colorFormat)
{
switch (colorFormat)
{
case D3DFMT_A16B16G16R16F:
return 16;
case D3DFMT_A32B32G32R32F:
return 32;
case D3DFMT_A2R10G10B10:
return 2;
case D3DFMT_A8R8G8B8:
return 8;
case D3DFMT_A1R5G5B5:
return 1;
case D3DFMT_X8R8G8B8:
case D3DFMT_R5G6B5:
return 0;
default: UNREACHABLE();
}
return 0;
}
unsigned int GetRedSize(D3DFORMAT colorFormat)
{
switch (colorFormat)
{
case D3DFMT_A16B16G16R16F:
return 16;
case D3DFMT_A32B32G32R32F:
return 32;
case D3DFMT_A2R10G10B10:
return 10;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
return 8;
case D3DFMT_A1R5G5B5:
case D3DFMT_R5G6B5:
return 5;
default: UNREACHABLE();
}
return 0;
}
unsigned int GetGreenSize(D3DFORMAT colorFormat)
{
switch (colorFormat)
{
case D3DFMT_A16B16G16R16F:
return 16;
case D3DFMT_A32B32G32R32F:
return 32;
case D3DFMT_A2R10G10B10:
return 10;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
return 8;
case D3DFMT_A1R5G5B5:
return 5;
case D3DFMT_R5G6B5:
return 6;
default: UNREACHABLE();
}
return 0;
}
unsigned int GetBlueSize(D3DFORMAT colorFormat)
{
switch (colorFormat)
{
case D3DFMT_A16B16G16R16F:
return 16;
case D3DFMT_A32B32G32R32F:
return 32;
case D3DFMT_A2R10G10B10:
return 10;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
return 8;
case D3DFMT_A1R5G5B5:
case D3DFMT_R5G6B5:
return 5;
default: UNREACHABLE();
}
return 0;
}
unsigned int GetDepthSize(D3DFORMAT depthFormat)
{
switch (depthFormat)
{
case D3DFMT_D16_LOCKABLE: return 16;
case D3DFMT_D32: return 32;
case D3DFMT_D15S1: return 15;
case D3DFMT_D24S8: return 24;
case D3DFMT_D24X8: return 24;
case D3DFMT_D24X4S4: return 24;
case D3DFMT_D16: return 16;
case D3DFMT_D32F_LOCKABLE: return 32;
case D3DFMT_D24FS8: return 24;
//case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only
//case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only
default:
UNREACHABLE();
}
return 0;
}
bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
{
@ -795,14 +664,6 @@ D3DFORMAT ConvertRenderbufferFormat(GLenum format)
}
}
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
{
if (type == D3DMULTISAMPLE_NONMASKABLE)
return 0;
else
return type;
}
D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
{
if (samples <= 1)
@ -816,6 +677,143 @@ D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
namespace dx2es
{
unsigned int GetStencilSize(D3DFORMAT stencilFormat)
{
switch(stencilFormat)
{
case D3DFMT_D24FS8:
case D3DFMT_D24S8:
return 8;
case D3DFMT_D24X4S4:
return 4;
case D3DFMT_D15S1:
return 1;
case D3DFMT_D16_LOCKABLE:
case D3DFMT_D32:
case D3DFMT_D24X8:
case D3DFMT_D32F_LOCKABLE:
case D3DFMT_D16:
return 0;
//case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
//case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
default:
return 0;
}
}
unsigned int GetAlphaSize(D3DFORMAT colorFormat)
{
switch (colorFormat)
{
case D3DFMT_A16B16G16R16F:
return 16;
case D3DFMT_A32B32G32R32F:
return 32;
case D3DFMT_A2R10G10B10:
return 2;
case D3DFMT_A8R8G8B8:
return 8;
case D3DFMT_A1R5G5B5:
return 1;
case D3DFMT_X8R8G8B8:
case D3DFMT_R5G6B5:
return 0;
default:
return 0;
}
}
unsigned int GetRedSize(D3DFORMAT colorFormat)
{
switch (colorFormat)
{
case D3DFMT_A16B16G16R16F:
return 16;
case D3DFMT_A32B32G32R32F:
return 32;
case D3DFMT_A2R10G10B10:
return 10;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
return 8;
case D3DFMT_A1R5G5B5:
case D3DFMT_R5G6B5:
return 5;
default:
return 0;
}
}
unsigned int GetGreenSize(D3DFORMAT colorFormat)
{
switch (colorFormat)
{
case D3DFMT_A16B16G16R16F:
return 16;
case D3DFMT_A32B32G32R32F:
return 32;
case D3DFMT_A2R10G10B10:
return 10;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
return 8;
case D3DFMT_A1R5G5B5:
return 5;
case D3DFMT_R5G6B5:
return 6;
default:
return 0;
}
}
unsigned int GetBlueSize(D3DFORMAT colorFormat)
{
switch (colorFormat)
{
case D3DFMT_A16B16G16R16F:
return 16;
case D3DFMT_A32B32G32R32F:
return 32;
case D3DFMT_A2R10G10B10:
return 10;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
return 8;
case D3DFMT_A1R5G5B5:
case D3DFMT_R5G6B5:
return 5;
default:
return 0;
}
}
unsigned int GetDepthSize(D3DFORMAT depthFormat)
{
switch (depthFormat)
{
case D3DFMT_D16_LOCKABLE: return 16;
case D3DFMT_D32: return 32;
case D3DFMT_D15S1: return 15;
case D3DFMT_D24S8: return 24;
case D3DFMT_D24X8: return 24;
case D3DFMT_D24X4S4: return 24;
case D3DFMT_D16: return 16;
case D3DFMT_D32F_LOCKABLE: return 32;
case D3DFMT_D24FS8: return 24;
//case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only
//case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only
default: return 0;
}
}
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
{
if (type == D3DMULTISAMPLE_NONMASKABLE)
return 0;
else
return type;
}
GLenum ConvertBackBufferFormat(D3DFORMAT format)
{
switch (format)

Просмотреть файл

@ -58,22 +58,23 @@ D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace);
DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter);
void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter);
unsigned int GetAlphaSize(D3DFORMAT colorFormat);
unsigned int GetRedSize(D3DFORMAT colorFormat);
unsigned int GetGreenSize(D3DFORMAT colorFormat);
unsigned int GetBlueSize(D3DFORMAT colorFormat);
unsigned int GetDepthSize(D3DFORMAT depthFormat);
unsigned int GetStencilSize(D3DFORMAT stencilFormat);
bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount);
D3DFORMAT ConvertRenderbufferFormat(GLenum format);
D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
}
namespace dx2es
{
GLuint GetAlphaSize(D3DFORMAT colorFormat);
GLuint GetRedSize(D3DFORMAT colorFormat);
GLuint GetGreenSize(D3DFORMAT colorFormat);
GLuint GetBlueSize(D3DFORMAT colorFormat);
GLuint GetDepthSize(D3DFORMAT depthFormat);
GLuint GetStencilSize(D3DFORMAT stencilFormat);
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
GLenum ConvertBackBufferFormat(D3DFORMAT format);
GLenum ConvertDepthStencilFormat(D3DFORMAT format);

Просмотреть файл

@ -0,0 +1,208 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// vertexconversion.h: A library of vertex conversion classes that can be used to build
// the FormatConverter objects used by the buffer conversion system.
#ifndef LIBGLESV2_VERTEXCONVERSION_H_
#define LIBGLESV2_VERTEXCONVERSION_H_
#include <cstddef>
#include <limits>
#include "libGLESv2/Context.h" // Defines Index
namespace gl
{
// Conversion types:
// static const bool identity: true if this is an identity transform, false otherwise
// static U convert(T): convert a single element from the input type to the output type
// typedef ... OutputType: the type produced by this conversion
template <class T>
struct Identity
{
static const bool identity = true;
typedef T OutputType;
static T convert(T x)
{
return x;
}
};
template <class FromT, class ToT>
struct Cast
{
static const bool identity = false;
typedef ToT OutputType;
static ToT convert(FromT x)
{
return static_cast<ToT>(x);
}
};
template <class T>
struct Cast<T, T>
{
static const bool identity = true;
typedef T OutputType;
static T convert(T x)
{
return static_cast<T>(x);
}
};
template <class T>
struct Normalize
{
static const bool identity = false;
typedef float OutputType;
static float convert(T x)
{
typedef std::numeric_limits<T> NL;
float f = static_cast<float>(x);
if (NL::is_signed)
{
// const float => VC2008 computes it at compile time
// static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
return (2*f+1)*divisor;
}
else
{
return f/NL::max();
}
}
};
template <class FromType, std::size_t ScaleBits>
struct FixedToFloat
{
static const bool identity = false;
typedef float OutputType;
static float convert(FromType x)
{
const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
return static_cast<float>(x) * divisor;
}
};
// Widen types:
// static const unsigned int initialWidth: number of components before conversion
// static const unsigned int finalWidth: number of components after conversion
// Float is supported at any size.
template <std::size_t N>
struct NoWiden
{
static const std::size_t initialWidth = N;
static const std::size_t finalWidth = N;
};
// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
template <std::size_t N>
struct WidenToEven
{
static const std::size_t initialWidth = N;
static const std::size_t finalWidth = N+(N&1);
};
template <std::size_t N>
struct WidenToFour
{
static const std::size_t initialWidth = N;
static const std::size_t finalWidth = 4;
};
// Most types have 0 and 1 that are just that.
template <class T>
struct SimpleDefaultValues
{
static T zero() { return static_cast<T>(0); }
static T one() { return static_cast<T>(1); }
};
// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
template <class T>
struct NormalizedDefaultValues
{
static T zero() { return static_cast<T>(0); }
static T one() { return std::numeric_limits<T>::max(); }
};
// Converter:
// static const bool identity: true if this is an identity transform (with no widening)
// static const std::size_t finalSize: number of bytes per output vertex
// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
struct VertexDataConverter
{
typedef typename Converter::OutputType OutputType;
typedef InT InputType;
static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
{
for (std::size_t i = 0; i < n; i++)
{
const InputType *ein = pointerAddBytes(in, i * stride);
copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
out += WidenRule::finalWidth;
}
}
static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
{
return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
}
private:
// Advance the given pointer by a number of bytes (not pointed-to elements).
template <class T>
static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
{
return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
}
static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
{
if (WidenRule::finalWidth > elementindex)
{
if (WidenRule::initialWidth > elementindex)
{
out[elementindex] = Converter::convert(in[elementindex]);
}
else
{
out[elementindex] = defaultvalue;
}
}
}
};
}
#endif // LIBGLESV2_VERTEXCONVERSION_H_

Просмотреть файл

@ -90,12 +90,8 @@ CanvasLayerD3D10::Initialize(const Data& aData)
HANDLE shareHandle = mGLContext ? mGLContext->GetD3DShareHandle() : nsnull;
if (shareHandle) {
HRESULT hr = device()->OpenSharedResource(shareHandle, __uuidof(ID3D10Texture2D), getter_AddRefs(mTexture));
if (SUCCEEDED(hr)) {
if (SUCCEEDED(hr))
mUsingSharedTexture = PR_TRUE;
// XXX for ANGLE, it's already the right-way up. If we start using NV GL-D3D interop
// however, we'll need to do the right thing.
mNeedsYFlip = PR_FALSE;
}
}
if (!mUsingSharedTexture) {

Просмотреть файл

@ -400,8 +400,8 @@ public:
if (!fInitialize(mEGLDisplay, NULL, NULL))
return PR_FALSE;
const char *version = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VERSION);
if (version && strstr(version, "ANGLE") != 0) {
const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
if (vendor && strstr(vendor, "TransGaming") != 0) {
mIsANGLE = PR_TRUE;
}