mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
merge m-c to devtools
This commit is contained in:
commit
f7149b4972
@ -477,7 +477,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||
eNoValue,
|
||||
eSwitchAction,
|
||||
eNoLiveAttr,
|
||||
kNoReqStates
|
||||
kNoReqStates,
|
||||
eARIASelectable
|
||||
},
|
||||
{
|
||||
"tablist",
|
||||
|
@ -1533,15 +1533,20 @@ nsAccessible::State()
|
||||
return states::DEFUNCT;
|
||||
|
||||
PRUint64 state = NativeState();
|
||||
// Apply ARIA states to be sure accessible states will be overriden.
|
||||
// Apply ARIA states to be sure accessible states will be overridden.
|
||||
ApplyARIAState(&state);
|
||||
|
||||
if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_PAGETAB) {
|
||||
if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_PAGETAB &&
|
||||
!(state & states::SELECTED) &&
|
||||
!mContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::aria_selected,
|
||||
nsAccessibilityAtoms::_false, eCaseMatters)) {
|
||||
// Special case: for tabs, focused implies selected, unless explicitly
|
||||
// false, i.e. aria-selected="false".
|
||||
if (state & states::FOCUSED) {
|
||||
state |= states::SELECTED;
|
||||
} else {
|
||||
// Expose 'selected' state on ARIA tab if the focus is on internal element
|
||||
// of related tabpanel.
|
||||
// If focus is in a child of the tab panel surely the tab is selected!
|
||||
nsCOMPtr<nsIAccessible> tabPanel = nsRelUtils::
|
||||
GetRelatedAccessible(this, nsIAccessibleRelation::RELATION_LABEL_FOR);
|
||||
|
||||
|
@ -1037,6 +1037,14 @@ nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsAccessibilityAtoms::aria_busy) {
|
||||
PRBool isOn = !aContent->AttrValueIs(aNameSpaceID, aAttribute,
|
||||
nsAccessibilityAtoms::_true, eCaseMatters);
|
||||
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aContent, states::BUSY, isOn);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsAccessibilityAtoms::selected ||
|
||||
aAttribute == nsAccessibilityAtoms::aria_selected) {
|
||||
// ARIA or XUL selection
|
||||
|
@ -26,35 +26,60 @@
|
||||
*/
|
||||
var gQueue = null;
|
||||
|
||||
// Debug stuff.
|
||||
//gA11yEventDumpID = "eventdump";
|
||||
// gA11yEventDumpToConsole = true;
|
||||
|
||||
function expandNode(aNodeOrID, bExpand)
|
||||
{
|
||||
this.DOMNode = getNode(aNodeOrID);
|
||||
|
||||
this.invoke = function expand_invoke() {
|
||||
this.invoke = function expandNode_invoke() {
|
||||
// Note: this should fire an EVENT_STATE_CHANGE
|
||||
this.DOMNode.setAttribute("aria-expanded", bExpand);
|
||||
};
|
||||
|
||||
this.check = function expand_check() {
|
||||
this.check = function expandNode_check() {
|
||||
testStates(aNodeOrID,
|
||||
bExpand ? STATE_EXPANDED : STATE_COLLAPSED,
|
||||
EXT_STATE_EXPANDABLE);
|
||||
};
|
||||
|
||||
this.getID = function changeValue_getID() {
|
||||
this.getID = function expandNode_getID() {
|
||||
return prettyName(aNodeOrID) + " aria-expanded changed";
|
||||
};
|
||||
}
|
||||
|
||||
function busyify(aNodeOrID, aBusy)
|
||||
{
|
||||
this.DOMNode = getNode(aNodeOrID);
|
||||
|
||||
this.invoke = function busyify_invoke() {
|
||||
this.DOMNode.setAttribute("aria-busy", aBusy);
|
||||
};
|
||||
|
||||
this.check = function busyify_check(event) {
|
||||
testStates(aNodeOrID,
|
||||
(aBusy ? STATE_BUSY : 0), 0,
|
||||
(aBusy ? 0 : STATE_BUSY), 0);
|
||||
};
|
||||
|
||||
this.getID = function busyify_getID() {
|
||||
return prettyName(aNodeOrID) + " aria-busy changed to " + aBusy;
|
||||
};
|
||||
}
|
||||
|
||||
function doTests()
|
||||
{
|
||||
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_STATE_CHANGE);
|
||||
gQueue = new eventQueue(EVENT_STATE_CHANGE);
|
||||
|
||||
gQueue.push(new expandNode("section", true));
|
||||
gQueue.push(new expandNode("section", false));
|
||||
gQueue.push(new expandNode("div", true));
|
||||
gQueue.push(new expandNode("div", false));
|
||||
|
||||
gQueue.push(new busyify("aria_doc", true));
|
||||
gQueue.push(new busyify("aria_doc", false));
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -71,6 +96,11 @@
|
||||
Mozilla Bug 551684
|
||||
</a>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=648133"
|
||||
title="fire state change event for aria-busy"
|
||||
Mozilla Bug 648133
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
@ -81,5 +111,7 @@
|
||||
<div id="section" role="section" aria-expanded="false">expandable section</div>
|
||||
<div id="div" aria-expanded="false">expandable native div</div>
|
||||
|
||||
<!-- aria-busy -->
|
||||
<div id="aria_doc" role="document" tabindex="0">A document</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
_TEST_FILES =\
|
||||
test_aria.html \
|
||||
test_aria_imgmap.html \
|
||||
test_aria_tabs.html \
|
||||
test_doc.html \
|
||||
test_docarticle.html \
|
||||
test_editablebody.html \
|
||||
|
137
accessible/tests/mochitest/states/test_aria_tabs.html
Normal file
137
accessible/tests/mochitest/states/test_aria_tabs.html
Normal file
@ -0,0 +1,137 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Test ARIA tab accessible selected state</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../states.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function focusARIATab(aID, aIsSelected)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
|
||||
this.invoke = function focusARIATab_invoke()
|
||||
{
|
||||
this.DOMNode.focus();
|
||||
}
|
||||
|
||||
this.check = function focusARIATab_check(aEvent)
|
||||
{
|
||||
testStates(this.DOMNode, aIsSelected ? STATE_SELECTED : 0, 0,
|
||||
aIsSelected ? 0 : STATE_SELECTED);
|
||||
}
|
||||
|
||||
this.getID = function focusARIATab_getID()
|
||||
{
|
||||
return "Focused ARIA Tab with aria-selected=" +
|
||||
(aIsSelected ? "true, should" : "false, shouldn't") +
|
||||
" have selected state on " + prettyName(aID);
|
||||
}
|
||||
}
|
||||
|
||||
function focusActiveDescendantTab(aTabID, aTabListID, aIsSelected)
|
||||
{
|
||||
this.DOMNode = getNode(aTabID);
|
||||
this.tabListDOMNode = getNode(aTabListID);
|
||||
|
||||
this.invoke = function focusActiveDescendantTab_invoke()
|
||||
{
|
||||
this.tabListDOMNode.setAttribute("aria-activedescendant", aTabID);
|
||||
this.tabListDOMNode.focus();
|
||||
}
|
||||
|
||||
this.check = function focusActiveDescendantTab_check(aEvent)
|
||||
{
|
||||
testStates(this.DOMNode, aIsSelected ? STATE_SELECTED : 0, 0,
|
||||
aIsSelected ? 0 : STATE_SELECTED);
|
||||
}
|
||||
|
||||
this.getID = function tabActiveDescendant_getID()
|
||||
{
|
||||
return "ARIA Tab with activedescendant " +
|
||||
(aIsSelected ? "should" : "shouldn't") +
|
||||
" have the selected state on " + prettyName(aTabID);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// simple tabs
|
||||
testStates("aria_tab1", 0, 0, STATE_SELECTED);
|
||||
testStates("aria_tab2", STATE_SELECTED);
|
||||
|
||||
// To make sure our focus != selected is truly under test, we need to
|
||||
// make sure our cache of what currently has focus is correct, which
|
||||
// we update asyncronously.
|
||||
gQueue = new eventQueue(EVENT_FOCUS);
|
||||
|
||||
gQueue.push(new focusARIATab("aria_tab1", true));
|
||||
gQueue.push(new focusARIATab("aria_tab3", false));
|
||||
gQueue.push(new focusARIATab("aria_tab2", true));
|
||||
|
||||
// selection through aria-activedescendant
|
||||
// Make sure initially setting it selects the tab.
|
||||
gQueue.push(new focusActiveDescendantTab("aria_tab5", "aria_tablist2", true));
|
||||
|
||||
// Now, make sure if one is selected selection gets transferred properly.
|
||||
gQueue.push(new focusActiveDescendantTab("aria_tab6", "aria_tablist2", true));
|
||||
|
||||
// Now, make sure the focused but explicitly unselected one behaves.
|
||||
gQueue.push(new focusActiveDescendantTab("aria_tab4", "aria_tablist2", false));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=653601"
|
||||
title="aria-selected ignored for ARIA tabs">
|
||||
Mozilla Bug 653601
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<!-- tab -->
|
||||
<div id="aria_tablist" role="tablist">
|
||||
<div id="aria_tab1" role="tab" tabindex="0">unselected tab</div>
|
||||
<div id="aria_tab2" role="tab" tabindex="0" aria-selected="true">selected tab</div>
|
||||
<div id="aria_tab3" role="tab" tabindex="0" aria-selected="false">focused explicitly unselected tab</div>
|
||||
</div>
|
||||
|
||||
<!-- test activeDescendant -->
|
||||
<div id="aria_tablist2" role="tablist" tabindex="0">
|
||||
<div id="aria_tab4" role="tab" aria-selected="false">focused explicitly unselected tab</div>
|
||||
<div id="aria_tab5" role="tab">initially selected tab</div>
|
||||
<div id="aria_tab6" role="tab">later selected tab</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -343,7 +343,8 @@
|
||||
footertype="promobox"
|
||||
position="after_start"
|
||||
hidden="true"
|
||||
orient="vertical"/>
|
||||
orient="vertical"
|
||||
role="alert"/>
|
||||
|
||||
<!-- Popup for site identity information -->
|
||||
<panel id="identity-popup"
|
||||
|
@ -907,7 +907,7 @@
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start">
|
||||
<xul:toolbarbutton anonid="closebutton"
|
||||
class="messageCloseButton popup-notification-closebutton"
|
||||
class="messageCloseButton popup-notification-closebutton tabbable"
|
||||
xbl:inherits="oncommand=closebuttoncommand"
|
||||
tooltiptext="&closeNotification.tooltip;"/>
|
||||
</xul:vbox>
|
||||
@ -954,7 +954,7 @@
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start">
|
||||
<xul:toolbarbutton anonid="closebutton"
|
||||
class="messageCloseButton popup-notification-closebutton"
|
||||
class="messageCloseButton popup-notification-closebutton tabbable"
|
||||
xbl:inherits="oncommand=closebuttoncommand"
|
||||
tooltiptext="&closeNotification.tooltip;"/>
|
||||
</xul:vbox>
|
||||
|
@ -315,7 +315,6 @@ WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@
|
||||
|
||||
MOZ_OPTIMIZE = @MOZ_OPTIMIZE@
|
||||
MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@
|
||||
MOZ_PGO_OPTIMIZE_FLAGS = @MOZ_PGO_OPTIMIZE_FLAGS@
|
||||
MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@
|
||||
MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@
|
||||
|
||||
|
@ -422,13 +422,8 @@ ifdef MODULE_OPTIMIZE_FLAGS
|
||||
CFLAGS += $(MODULE_OPTIMIZE_FLAGS)
|
||||
CXXFLAGS += $(MODULE_OPTIMIZE_FLAGS)
|
||||
else
|
||||
ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
|
||||
CFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
|
||||
CXXFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
|
||||
else
|
||||
CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
|
||||
CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
|
||||
endif # neq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
|
||||
endif # MODULE_OPTIMIZE_FLAGS
|
||||
else
|
||||
CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
|
||||
|
20
configure.in
20
configure.in
@ -2188,12 +2188,10 @@ ia64*-hpux*)
|
||||
esac
|
||||
# If we're building with --enable-profiling, we need a frame pointer.
|
||||
if test -z "$MOZ_PROFILING"; then
|
||||
MOZ_FRAMEPTR_FLAGS="-fomit-frame-pointer"
|
||||
MOZ_OPTIMIZE_FLAGS="-O3 -fomit-frame-pointer"
|
||||
else
|
||||
MOZ_FRAMEPTR_FLAGS="-fno-omit-frame-pointer"
|
||||
MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
|
||||
fi
|
||||
MOZ_PGO_OPTIMIZE_FLAGS="-O3 $MOZ_FRAMEPTR_FLAGS"
|
||||
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK $MOZ_FRAMEPTR_FLAGS"
|
||||
MOZ_DEBUG_FLAGS="-g"
|
||||
fi
|
||||
|
||||
@ -6140,9 +6138,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"
|
||||
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"
|
||||
|
||||
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\\:\\\\/'`
|
||||
fi
|
||||
|
||||
MOZ_ANGLE=
|
||||
|
||||
@ -6154,12 +6155,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
|
||||
@ -7185,7 +7186,6 @@ AC_SUBST(MOZ_OPTIMIZE)
|
||||
AC_SUBST(MOZ_OPTIMIZE_FLAGS)
|
||||
AC_SUBST(MOZ_OPTIMIZE_LDFLAGS)
|
||||
AC_SUBST(MOZ_OPTIMIZE_SIZE_TWEAK)
|
||||
AC_SUBST(MOZ_PGO_OPTIMIZE_FLAGS)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable generation of debug symbols
|
||||
|
@ -41,11 +41,9 @@ interface nsIDOMEventListener;
|
||||
interface nsIDOMBlob;
|
||||
interface nsIDOMFileError;
|
||||
|
||||
[scriptable, uuid(3d77e784-1459-4206-b8a2-0855d826f569)]
|
||||
[scriptable, uuid(f186170f-f07c-4f0b-9e3c-08f7dd496e74)]
|
||||
interface nsIDOMFileReader : nsISupports
|
||||
{
|
||||
[implicit_jscontext]
|
||||
void readAsArrayBuffer(in nsIDOMBlob filedata);
|
||||
void readAsBinaryString(in nsIDOMBlob filedata);
|
||||
void readAsText(in nsIDOMBlob filedata, [optional] in DOMString encoding);
|
||||
void readAsDataURL(in nsIDOMBlob file);
|
||||
@ -57,8 +55,7 @@ interface nsIDOMFileReader : nsISupports
|
||||
const unsigned short DONE = 2;
|
||||
readonly attribute unsigned short readyState;
|
||||
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval result;
|
||||
readonly attribute DOMString result;
|
||||
readonly attribute nsIDOMFileError error;
|
||||
};
|
||||
|
||||
|
@ -77,9 +77,6 @@
|
||||
#include "nsLayoutStatics.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsFileDataProtocolHandler.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "xpcquickstubs.h"
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#define LOAD_STR "load"
|
||||
#define ERROR_STR "error"
|
||||
@ -104,21 +101,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader,
|
||||
nsXHREventTarget)
|
||||
tmp->mResultArrayBuffer = nsnull;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFile)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressNotifier)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsDOMFileReader,
|
||||
nsXHREventTarget)
|
||||
if(tmp->mResultArrayBuffer) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mResultArrayBuffer,
|
||||
"mResultArrayBuffer")
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
DOMCI_DATA(FileReader, nsDOMFileReader)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileReader)
|
||||
@ -135,13 +123,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMFileReader, nsXHREventTarget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMFileReader, nsXHREventTarget)
|
||||
|
||||
//array buffer holder root/unroot
|
||||
void
|
||||
nsDOMFileReader::RootResultArrayBuffer()
|
||||
{
|
||||
nsContentUtils::PreserveWrapper(static_cast<nsPIDOMEventTarget*>(this), this);
|
||||
}
|
||||
|
||||
//nsICharsetDetectionObserver
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -156,14 +137,12 @@ nsDOMFileReader::Notify(const char *aCharset, nsDetectionConfident aConf)
|
||||
nsDOMFileReader::nsDOMFileReader()
|
||||
: mFileData(nsnull),
|
||||
mDataLen(0), mDataFormat(FILE_AS_BINARY),
|
||||
mResultArrayBuffer(nsnull),
|
||||
mReadyState(nsIDOMFileReader::EMPTY),
|
||||
mProgressEventWasDelayed(PR_FALSE),
|
||||
mTimerIsActive(PR_FALSE),
|
||||
mReadTotal(0), mReadTransferred(0)
|
||||
{
|
||||
nsLayoutStatics::AddRef();
|
||||
SetDOMStringToNull(mResult);
|
||||
}
|
||||
|
||||
nsDOMFileReader::~nsDOMFileReader()
|
||||
@ -256,21 +235,9 @@ nsDOMFileReader::GetReadyState(PRUint16 *aReadyState)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMFileReader::GetResult(JSContext* aCx, jsval* aResult)
|
||||
nsDOMFileReader::GetResult(nsAString& aResult)
|
||||
{
|
||||
if (mDataFormat == FILE_AS_ARRAYBUFFER) {
|
||||
if (mReadyState == nsIDOMFileReader::DONE) {
|
||||
*aResult = OBJECT_TO_JSVAL(mResultArrayBuffer);
|
||||
} else {
|
||||
*aResult = JSVAL_NULL;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString tmpResult = mResult;
|
||||
if (!xpc_qsStringToJsval(aCx, tmpResult, aResult)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
aResult = mResult;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -281,29 +248,23 @@ nsDOMFileReader::GetError(nsIDOMFileError** aError)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMFileReader::ReadAsArrayBuffer(nsIDOMBlob* aFile, JSContext* aCx)
|
||||
{
|
||||
return ReadFileContent(aCx, aFile, EmptyString(), FILE_AS_ARRAYBUFFER);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMFileReader::ReadAsBinaryString(nsIDOMBlob* aFile)
|
||||
{
|
||||
return ReadFileContent(nsnull, aFile, EmptyString(), FILE_AS_BINARY);
|
||||
return ReadFileContent(aFile, EmptyString(), FILE_AS_BINARY);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMFileReader::ReadAsText(nsIDOMBlob* aFile,
|
||||
const nsAString &aCharset)
|
||||
{
|
||||
return ReadFileContent(nsnull, aFile, aCharset, FILE_AS_TEXT);
|
||||
return ReadFileContent(aFile, aCharset, FILE_AS_TEXT);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMFileReader::ReadAsDataURL(nsIDOMBlob* aFile)
|
||||
{
|
||||
return ReadFileContent(nsnull, aFile, EmptyString(), FILE_AS_DATAURL);
|
||||
return ReadFileContent(aFile, EmptyString(), FILE_AS_DATAURL);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -321,7 +282,6 @@ nsDOMFileReader::Abort()
|
||||
|
||||
//Revert status, result and readystate attributes
|
||||
SetDOMStringToNull(mResult);
|
||||
mResultArrayBuffer = nsnull;
|
||||
mReadyState = nsIDOMFileReader::DONE;
|
||||
mError = new nsDOMFileError(nsIDOMFileError::ABORT_ERR);
|
||||
|
||||
@ -424,14 +384,6 @@ nsDOMFileReader::OnDataAvailable(nsIRequest *aRequest,
|
||||
&bytesRead);
|
||||
NS_ASSERTION(bytesRead == aCount, "failed to read data");
|
||||
}
|
||||
else if (mDataFormat == FILE_AS_ARRAYBUFFER) {
|
||||
js::ArrayBuffer* abuf = js::ArrayBuffer::fromJSObject(mResultArrayBuffer);
|
||||
NS_ASSERTION(abuf, "What happened?");
|
||||
|
||||
PRUint32 bytesRead = 0;
|
||||
aInputStream->Read((char*)abuf->data + aOffset, aCount, &bytesRead);
|
||||
NS_ASSERTION(bytesRead == aCount, "failed to read data");
|
||||
}
|
||||
else {
|
||||
//Update memory buffer to reflect the contents of the file
|
||||
mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount);
|
||||
@ -487,8 +439,6 @@ nsDOMFileReader::OnStopRequest(nsIRequest *aRequest,
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
switch (mDataFormat) {
|
||||
case FILE_AS_ARRAYBUFFER:
|
||||
break; //Already accumulated mResultArrayBuffer
|
||||
case FILE_AS_BINARY:
|
||||
break; //Already accumulated mResult
|
||||
case FILE_AS_TEXT:
|
||||
@ -518,8 +468,7 @@ nsDOMFileReader::OnStopRequest(nsIRequest *aRequest,
|
||||
// Helper methods
|
||||
|
||||
nsresult
|
||||
nsDOMFileReader::ReadFileContent(JSContext* aCx,
|
||||
nsIDOMBlob* aFile,
|
||||
nsDOMFileReader::ReadFileContent(nsIDOMBlob* aFile,
|
||||
const nsAString &aCharset,
|
||||
eDataFormat aDataFormat)
|
||||
{
|
||||
@ -564,15 +513,6 @@ nsDOMFileReader::ReadFileContent(JSContext* aCx,
|
||||
//FileReader should be in loading state here
|
||||
mReadyState = nsIDOMFileReader::LOADING;
|
||||
DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
|
||||
|
||||
if (mDataFormat == FILE_AS_ARRAYBUFFER) {
|
||||
RootResultArrayBuffer();
|
||||
mResultArrayBuffer = js_CreateArrayBuffer(aCx, mReadTotal);
|
||||
if (!mResultArrayBuffer) {
|
||||
NS_WARNING("Failed to create JS array buffer");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -80,8 +80,7 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_NSIDOMFILEREADER
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsDOMFileReader,
|
||||
nsXHREventTarget)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMFileReader, nsXHREventTarget)
|
||||
|
||||
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::);
|
||||
|
||||
@ -110,18 +109,15 @@ public:
|
||||
void DispatchProgressEvent(const nsAString& aType);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
void RootResultArrayBuffer();
|
||||
|
||||
protected:
|
||||
enum eDataFormat {
|
||||
FILE_AS_ARRAYBUFFER,
|
||||
FILE_AS_BINARY,
|
||||
FILE_AS_TEXT,
|
||||
FILE_AS_DATAURL
|
||||
};
|
||||
|
||||
nsresult ReadFileContent(JSContext* aCx, nsIDOMBlob *aFile, const nsAString &aCharset, eDataFormat aDataFormat);
|
||||
nsresult ReadFileContent(nsIDOMBlob *aFile, const nsAString &aCharset, eDataFormat aDataFormat);
|
||||
nsresult GetAsText(const nsACString &aCharset,
|
||||
const char *aFileData, PRUint32 aDataLen, nsAString &aResult);
|
||||
nsresult GetAsDataURL(nsIDOMBlob *aFile, const char *aFileData, PRUint32 aDataLen, nsAString &aResult);
|
||||
@ -143,8 +139,6 @@ protected:
|
||||
|
||||
eDataFormat mDataFormat;
|
||||
|
||||
JSObject* mResultArrayBuffer;
|
||||
|
||||
nsString mResult;
|
||||
PRUint16 mReadyState;
|
||||
|
||||
|
@ -426,8 +426,7 @@ nsXMLHttpRequest::nsXMLHttpRequest()
|
||||
mErrorLoad(PR_FALSE), mTimerIsActive(PR_FALSE),
|
||||
mProgressEventWasDelayed(PR_FALSE),
|
||||
mLoadLengthComputable(PR_FALSE), mLoadTotal(0),
|
||||
mFirstStartRequestSeen(PR_FALSE),
|
||||
mResultArrayBuffer(nsnull)
|
||||
mFirstStartRequestSeen(PR_FALSE)
|
||||
{
|
||||
mResponseBodyUnicode.SetIsVoid(PR_TRUE);
|
||||
nsLayoutStatics::AddRef();
|
||||
@ -451,12 +450,6 @@ nsXMLHttpRequest::~nsXMLHttpRequest()
|
||||
nsLayoutStatics::Release();
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLHttpRequest::RootResultArrayBuffer()
|
||||
{
|
||||
nsContentUtils::PreserveWrapper(static_cast<nsPIDOMEventTarget*>(this), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This Init method is called from the factory constructor.
|
||||
*/
|
||||
@ -579,9 +572,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
|
||||
nsIXMLHttpRequestUpload)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
|
||||
nsXHREventTarget)
|
||||
tmp->mResultArrayBuffer = nsnull;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest)
|
||||
@ -599,14 +592,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mUpload)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsXMLHttpRequest,
|
||||
nsXHREventTarget)
|
||||
if(tmp->mResultArrayBuffer) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mResultArrayBuffer,
|
||||
"mResultArrayBuffer")
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
DOMCI_DATA(XMLHttpRequest, nsXMLHttpRequest)
|
||||
|
||||
// QueryInterface implementation for nsXMLHttpRequest
|
||||
@ -854,20 +839,27 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponseText(nsAString& aResponseText)
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsXMLHttpRequest::CreateResponseArrayBuffer(JSContext *aCx)
|
||||
nsresult nsXMLHttpRequest::GetResponseArrayBuffer(jsval *aResult)
|
||||
{
|
||||
if (!aCx)
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
if (!cx)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 dataLen = mResponseBody.Length();
|
||||
RootResultArrayBuffer();
|
||||
mResultArrayBuffer = js_CreateArrayBuffer(aCx, dataLen);
|
||||
if (!mResultArrayBuffer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!(mState & (XML_HTTP_REQUEST_DONE |
|
||||
XML_HTTP_REQUEST_LOADING))) {
|
||||
*aResult = JSVAL_NULL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32 dataLen = mResponseBody.Length();
|
||||
JSObject *obj = js_CreateArrayBuffer(cx, dataLen);
|
||||
if (!obj)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*aResult = OBJECT_TO_JSVAL(obj);
|
||||
|
||||
if (dataLen > 0) {
|
||||
js::ArrayBuffer *abuf = js::ArrayBuffer::fromJSObject(mResultArrayBuffer);
|
||||
js::ArrayBuffer *abuf = js::ArrayBuffer::fromJSObject(obj);
|
||||
NS_ASSERTION(abuf, "What happened?");
|
||||
memcpy(abuf->data, mResponseBody.BeginReading(), dataLen);
|
||||
}
|
||||
@ -962,11 +954,7 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponse(JSContext *aCx, jsval *aResult)
|
||||
|
||||
case XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER:
|
||||
if (mState & XML_HTTP_REQUEST_DONE) {
|
||||
if (!mResultArrayBuffer) {
|
||||
rv = CreateResponseArrayBuffer(aCx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
*aResult = OBJECT_TO_JSVAL(mResultArrayBuffer);
|
||||
rv = GetResponseArrayBuffer(aResult);
|
||||
} else {
|
||||
*aResult = JSVAL_NULL;
|
||||
}
|
||||
@ -1085,8 +1073,7 @@ nsXMLHttpRequest::Abort()
|
||||
mResponseBodyUnicode.SetIsVoid(PR_TRUE);
|
||||
mResponseBlob = nsnull;
|
||||
mState |= XML_HTTP_REQUEST_ABORTED;
|
||||
mResultArrayBuffer = nsnull;
|
||||
|
||||
|
||||
if (!(mState & (XML_HTTP_REQUEST_UNSENT |
|
||||
XML_HTTP_REQUEST_OPENED |
|
||||
XML_HTTP_REQUEST_DONE))) {
|
||||
|
@ -208,11 +208,11 @@ public:
|
||||
|
||||
void SetRequestObserver(nsIRequestObserver* aObserver);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsXMLHttpRequest,
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequest,
|
||||
nsXHREventTarget)
|
||||
|
||||
PRBool AllowUploadProgress();
|
||||
void RootResultArrayBuffer();
|
||||
|
||||
|
||||
protected:
|
||||
friend class nsMultipartProxyListener;
|
||||
|
||||
@ -224,7 +224,7 @@ protected:
|
||||
PRUint32 toOffset,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount);
|
||||
nsresult CreateResponseArrayBuffer(JSContext* aCx);
|
||||
nsresult GetResponseArrayBuffer(jsval *aResult);
|
||||
void CreateResponseBlob(nsIRequest *request);
|
||||
// Change the state of the object with this. The broadcast argument
|
||||
// determines if the onreadystatechange listener should be called.
|
||||
@ -345,8 +345,6 @@ protected:
|
||||
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
nsCOMPtr<nsIChannel> mNewRedirectChannel;
|
||||
|
||||
JSObject* mResultArrayBuffer;
|
||||
};
|
||||
|
||||
// helper class to expose a progress DOM Event
|
||||
|
@ -134,16 +134,6 @@ ab = xhr.response;
|
||||
ok(ab != null, "should have a non-null arraybuffer");
|
||||
arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
|
||||
|
||||
// test array buffer GetResult returns the same object
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", 'file_XHR_binary1.bin', false);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.send(null)
|
||||
is(xhr.status, 200, "wrong status");
|
||||
checkResponseTextAccessThrows(xhr);
|
||||
checkResponseXMLAccessThrows(xhr);
|
||||
is(xhr.response, xhr.response, "returns the same ArrayBuffer");
|
||||
|
||||
// test response (responseType='blob')
|
||||
var onloadCount = 0;
|
||||
function checkOnloadCount() {
|
||||
|
@ -98,18 +98,6 @@ is(onloadHasRunBinary, false, "binary loading must be async");
|
||||
is(onloadStartHasRunBinary, true, "binary loadstart should fire sync");
|
||||
expectedTestCount++;
|
||||
|
||||
var onloadHasRunArrayBuffer = false;
|
||||
var onloadStartHasRunArrayBuffer = false;
|
||||
r = new FileReader();
|
||||
is(r.readyState, FileReader.EMPTY, "correct initial arrayBuffer readyState");
|
||||
r.addEventListener("load", function() { onloadHasRunArrayBuffer = true }, false);
|
||||
r.addEventListener("loadstart", function() { onloadStartHasRunArrayBuffer = true }, false);
|
||||
r.readAsArrayBuffer(binaryFile);
|
||||
r.onload = getLoadHandlerForArrayBuffer(testBinaryData, testBinaryData.length, "array buffer reading");
|
||||
is(r.readyState, FileReader.LOADING, "correct loading arrayBuffer readyState");
|
||||
is(onloadHasRunArrayBuffer, false, "arrayBuffer loading must be async");
|
||||
is(onloadStartHasRunArrayBuffer, true, "arrayBuffer loadstart should fire sync");
|
||||
expectedTestCount++;
|
||||
|
||||
// Test a variety of encodings, and make sure they work properly
|
||||
r = new FileReader();
|
||||
@ -136,14 +124,6 @@ r.onload = getLoadHandler(testTextData,
|
||||
"utf16 reading");
|
||||
expectedTestCount++;
|
||||
|
||||
// Test get result without reading
|
||||
r = new FileReader();
|
||||
is(r.readyState, FileReader.EMPTY,
|
||||
"readyState in test reader get result without reading");
|
||||
is(r.error, null,
|
||||
"no error in test reader get result without reading");
|
||||
is(r.result, null,
|
||||
"result in test reader get result without reading");
|
||||
|
||||
// Test loading an empty file works (and doesn't crash!)
|
||||
var emptyFile = createFileWithData("");
|
||||
@ -168,16 +148,12 @@ r.onload = getLoadHandler("", 0, "empty binary string reading");
|
||||
r.readAsBinaryString(emptyFile);
|
||||
expectedTestCount++;
|
||||
|
||||
r = new FileReader();
|
||||
r.onload = getLoadHandlerForArrayBuffer("", 0, "empty array buffer reading");
|
||||
r.readAsArrayBuffer(emptyFile);
|
||||
expectedTestCount++;
|
||||
|
||||
r = new FileReader();
|
||||
r.onload = getLoadHandler(convertToDataURL(""), 0, "empt binary string reading");
|
||||
r.readAsDataURL(emptyFile);
|
||||
expectedTestCount++;
|
||||
|
||||
|
||||
// Test reusing a FileReader to read multiple times
|
||||
r = new FileReader();
|
||||
r.onload = getLoadHandler(testASCIIData,
|
||||
@ -227,39 +203,6 @@ r.addEventListener("load", makeAnotherReadListener3, false);
|
||||
r.readAsDataURL(binaryFile);
|
||||
expectedTestCount += 2;
|
||||
|
||||
r = new FileReader();
|
||||
r.onload = getLoadHandlerForArrayBuffer(testBinaryData,
|
||||
testBinaryData.length,
|
||||
"to-be-reused reading arrayBuffer")
|
||||
var makeAnotherReadListener4 = function(event) {
|
||||
r = event.target;
|
||||
r.removeEventListener("load", makeAnotherReadListener4, false);
|
||||
r.onload = getLoadHandlerForArrayBuffer(testBinaryData,
|
||||
testBinaryData.length,
|
||||
"reused reading arrayBuffer");
|
||||
r.readAsArrayBuffer(binaryFile);
|
||||
};
|
||||
r.addEventListener("load", makeAnotherReadListener4, false);
|
||||
r.readAsArrayBuffer(binaryFile);
|
||||
expectedTestCount += 2;
|
||||
|
||||
// Test first reading as ArrayBuffer then read as something else
|
||||
// (BinaryString) and doesn't crash
|
||||
r = new FileReader();
|
||||
r.onload = getLoadHandlerForArrayBuffer(testBinaryData,
|
||||
testBinaryData.length,
|
||||
"to-be-reused reading arrayBuffer")
|
||||
var makeAnotherReadListener5 = function(event) {
|
||||
r = event.target;
|
||||
r.removeEventListener("load", makeAnotherReadListener5, false);
|
||||
r.onload = getLoadHandler(testBinaryData,
|
||||
testBinaryData.length,
|
||||
"reused reading binary string");
|
||||
r.readAsBinaryString(binaryFile);
|
||||
};
|
||||
r.addEventListener("load", makeAnotherReadListener5, false);
|
||||
r.readAsArrayBuffer(binaryFile);
|
||||
expectedTestCount += 2;
|
||||
|
||||
//Test data-URI encoding on differing file sizes
|
||||
dataurldata = testBinaryData.substr(0, testBinaryData.length -
|
||||
@ -379,37 +322,9 @@ function getLoadHandler(expectedResult, expectedLength, testName) {
|
||||
is(event.lengthComputable, true,
|
||||
"lengthComputable in test " + testName);
|
||||
is(event.loaded, expectedLength,
|
||||
"loaded in test " + testName);
|
||||
is(event.total, expectedLength,
|
||||
"total in test " + testName);
|
||||
testHasRun();
|
||||
}
|
||||
}
|
||||
|
||||
function getLoadHandlerForArrayBuffer(expectedResult, expectedLength, testName) {
|
||||
return function (event) {
|
||||
is(event.target.readyState, FileReader.DONE,
|
||||
"readyState in test " + testName);
|
||||
is(event.target.error, null,
|
||||
"no error in test " + testName);
|
||||
is(event.lengthComputable, true,
|
||||
"lengthComputable in test " + testName);
|
||||
is(event.loaded, expectedLength,
|
||||
"loaded in test " + testName);
|
||||
is(event.total, expectedLength,
|
||||
"total in test " + testName);
|
||||
is(event.target.result.byteLength, expectedLength,
|
||||
"array buffer size in test " + testName);
|
||||
var u8v = new Uint8Array(event.target.result);
|
||||
is(String.fromCharCode.apply(String, u8v), expectedResult,
|
||||
"array buffer contents in test " + testName);
|
||||
u8v = null;
|
||||
SpecialPowers.gc();
|
||||
is(event.target.result.byteLength, expectedLength,
|
||||
"array buffer size after gc in test " + testName);
|
||||
u8v = new Uint8Array(event.target.result);
|
||||
is(String.fromCharCode.apply(String, u8v), expectedResult,
|
||||
"array buffer contents after gc in test " + testName);
|
||||
"lengthComputable in test " + testName);
|
||||
testHasRun();
|
||||
}
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -8300,8 +8300,10 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
GetCurScrollPos(ScrollOrientation_X, &cx);
|
||||
GetCurScrollPos(ScrollOrientation_Y, &cy);
|
||||
|
||||
// We scroll the window precisely when we fire a hashchange event.
|
||||
if (doHashchange) {
|
||||
// We scroll whenever we're not doing a history load. Note that
|
||||
// sometimes we might scroll even if we don't fire a hashchange
|
||||
// event! See bug 653741.
|
||||
if (!aSHEntry) {
|
||||
// Take the '#' off the hashes before passing them to
|
||||
// ScrollToAnchor.
|
||||
nsDependentCSubstring curHashName(curHash, 1);
|
||||
|
@ -101,6 +101,8 @@ _TEST_FILES = \
|
||||
test_bug640387_1.html \
|
||||
test_bug640387_2.html \
|
||||
file_bug640387.html \
|
||||
test_bug653741.html \
|
||||
file_bug653741.html \
|
||||
test_framedhistoryframes.html \
|
||||
test_windowedhistoryframes.html \
|
||||
historyframes.html \
|
||||
|
13
docshell/test/file_bug653741.html
Normal file
13
docshell/test/file_bug653741.html
Normal file
@ -0,0 +1,13 @@
|
||||
<html>
|
||||
<body onload='(parent || opener).childLoad()'>
|
||||
|
||||
<div style='height:500px; background:yellow'>
|
||||
<a id='#top'>Top of the page</a>
|
||||
</div>
|
||||
|
||||
<div id='bottom'>
|
||||
<a id='#bottom'>Bottom of the page</a>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
50
docshell/test/test_bug653741.html
Normal file
50
docshell/test/test_bug653741.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=653741
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 653741</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=653741">Mozilla Bug 653741</a>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 653741 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function childLoad() {
|
||||
// Spin the event loop so we leave the onload handler.
|
||||
SimpleTest.executeSoon(childLoad2);
|
||||
}
|
||||
|
||||
function childLoad2() {
|
||||
let cw = $('iframe').contentWindow;
|
||||
|
||||
// Save the Y offset. For sanity's sake, make sure it's not 0, because we
|
||||
// should be at the bottom of the page!
|
||||
let origYOffset = cw.pageYOffset;
|
||||
ok(origYOffset != 0, 'Original Y offset is not 0.');
|
||||
|
||||
// Scroll the iframe to the top, then navigate to #bottom again.
|
||||
cw.scrollTo(0, 0);
|
||||
|
||||
// Our current location is #bottom, so this should scroll us down to the
|
||||
// bottom again.
|
||||
cw.location = cw.location + '';
|
||||
|
||||
is(cw.pageYOffset, origYOffset, 'Correct offset after reloading page.');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<iframe height='100px' id='iframe' src='file_bug653741.html#bottom'></iframe>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -867,6 +867,7 @@ ContentParent::RecvSetURITitle(const IPC::URI& uri,
|
||||
bool
|
||||
ContentParent::RecvShowFilePicker(const PRInt16& mode,
|
||||
const PRInt16& selectedType,
|
||||
const PRBool& addToRecentDocs,
|
||||
const nsString& title,
|
||||
const nsString& defaultFile,
|
||||
const nsString& defaultExtension,
|
||||
@ -892,7 +893,9 @@ ContentParent::RecvShowFilePicker(const PRInt16& mode,
|
||||
*result = filePicker->Init(window, title, mode);
|
||||
if (NS_FAILED(*result))
|
||||
return true;
|
||||
|
||||
|
||||
filePicker->SetAddToRecentDocs(addToRecentDocs);
|
||||
|
||||
PRUint32 count = filters.Length();
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
filePicker->AppendFilter(filterNames[i], filters[i]);
|
||||
|
@ -178,6 +178,7 @@ private:
|
||||
|
||||
virtual bool RecvShowFilePicker(const PRInt16& mode,
|
||||
const PRInt16& selectedType,
|
||||
const PRBool& addToRecentDocs,
|
||||
const nsString& title,
|
||||
const nsString& defaultFile,
|
||||
const nsString& defaultExtension,
|
||||
|
@ -144,7 +144,7 @@ parent:
|
||||
async SetURITitle(URI uri, nsString title);
|
||||
|
||||
// filepicker remoting
|
||||
sync ShowFilePicker(PRInt16 mode, PRInt16 selectedType,
|
||||
sync ShowFilePicker(PRInt16 mode, PRInt16 selectedType, PRBool addToRecentDocs,
|
||||
nsString title, nsString defaultFile, nsString defaultExtension,
|
||||
nsString[] filters, nsString[] filterNames)
|
||||
returns (nsString[] files, PRInt16 retValue, nsresult result);
|
||||
|
@ -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
|
||||
== Applied local patches ==
|
||||
|
||||
angle-fixes.patch - fix angle issues 51 & 52
|
||||
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-nspr-misc.patch - don't bother with ANGLE_OS detection with NSPR
|
||||
== How to update this ANGLE copy ==
|
||||
|
||||
angle-pbuffers.patch - add pbuffer support to ANGLE, and d3d texture handle query (angle issue 91)
|
||||
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();
|
466
gfx/angle/angle-makefiles.patch
Normal file
466
gfx/angle/angle-makefiles.patch
Normal file
@ -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]);
|
222
gfx/angle/angle-renaming-debug.patch
Normal file
222
gfx/angle/angle-renaming-debug.patch
Normal file
@ -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: ////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
427
gfx/angle/extensions/ANGLE_framebuffer_blit.txt
Normal file
427
gfx/angle/extensions/ANGLE_framebuffer_blit.txt
Normal file
@ -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
|
||||
|
363
gfx/angle/extensions/ANGLE_framebuffer_multisample.txt
Normal file
363
gfx/angle/extensions/ANGLE_framebuffer_multisample.txt
Normal file
@ -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
|
591
gfx/angle/extensions/ANGLE_timer_query.txt
Normal file
591
gfx/angle/extensions/ANGLE_timer_query.txt
Normal file
@ -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.
|
88
gfx/angle/extensions/EGL_ANGLE_query_surface_pointer.txt
Normal file
88
gfx/angle/extensions/EGL_ANGLE_query_surface_pointer.txt
Normal file
@ -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,18 +62,20 @@ 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.
|
||||
typedef enum {
|
||||
SH_VALIDATE = 0,
|
||||
SH_VALIDATE_LOOP_INDEXING = 0x0001,
|
||||
SH_INTERMEDIATE_TREE = 0x0002,
|
||||
SH_OBJECT_CODE = 0x0004,
|
||||
SH_ATTRIBUTES_UNIFORMS = 0x0008,
|
||||
SH_LINE_DIRECTIVES = 0x0010,
|
||||
SH_SOURCE_PATH = 0x0200
|
||||
SH_VALIDATE = 0,
|
||||
SH_VALIDATE_LOOP_INDEXING = 0x0001,
|
||||
SH_INTERMEDIATE_TREE = 0x0002,
|
||||
SH_OBJECT_CODE = 0x0004,
|
||||
SH_ATTRIBUTES_UNIFORMS = 0x0008,
|
||||
SH_LINE_DIRECTIVES = 0x0010,
|
||||
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;
|
||||
|
172
gfx/angle/src/compiler/ForLoopUnroll.cpp
Normal file
172
gfx/angle/src/compiler/ForLoopUnroll.cpp
Normal file
@ -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();
|
||||
}
|
||||
|
46
gfx/angle/src/compiler/ForLoopUnroll.h
Normal file
46
gfx/angle/src/compiler/ForLoopUnroll.h
Normal file
@ -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,17 +353,15 @@ 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);"));
|
||||
s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
|
||||
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);"));
|
||||
s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
|
||||
|
||||
s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
|
||||
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);"));
|
||||
}
|
||||
s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
|
||||
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;
|
||||
|
61
gfx/angle/src/compiler/MapLongVariableNames.cpp
Normal file
61
gfx/angle/src/compiler/MapLongVariableNames.cpp
Normal file
@ -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;
|
||||
}
|
34
gfx/angle/src/compiler/MapLongVariableNames.h
Normal file
34
gfx/angle/src/compiler/MapLongVariableNames.h
Normal file
@ -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,7 +195,10 @@ const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type,
|
||||
void TOutputGLSL::visitSymbol(TIntermSymbol* node)
|
||||
{
|
||||
TInfoSinkBase& out = objSink();
|
||||
out << node->getSymbol();
|
||||
if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
|
||||
out << mLoopUnroll.GetLoopIndexValue(node);
|
||||
else
|
||||
out << node->getSymbol();
|
||||
|
||||
if (mDeclaringVariables && node->getType().isArray())
|
||||
out << arrayBrackets(node->getType());
|
||||
@ -615,18 +618,20 @@ bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
|
||||
TLoopType loopType = node->getType();
|
||||
if (loopType == ELoopFor) // for loop
|
||||
{
|
||||
out << "for (";
|
||||
if (node->getInit())
|
||||
node->getInit()->traverse(this);
|
||||
out << "; ";
|
||||
if (!node->getUnrollFlag()) {
|
||||
out << "for (";
|
||||
if (node->getInit())
|
||||
node->getInit()->traverse(this);
|
||||
out << "; ";
|
||||
|
||||
if (node->getCondition())
|
||||
node->getCondition()->traverse(this);
|
||||
out << "; ";
|
||||
if (node->getCondition())
|
||||
node->getCondition()->traverse(this);
|
||||
out << "; ";
|
||||
|
||||
if (node->getExpression())
|
||||
node->getExpression()->traverse(this);
|
||||
out << ")\n";
|
||||
if (node->getExpression())
|
||||
node->getExpression()->traverse(this);
|
||||
out << ")\n";
|
||||
}
|
||||
}
|
||||
else if (loopType == ELoopWhile) // while loop
|
||||
{
|
||||
@ -642,7 +647,22 @@ bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
|
||||
}
|
||||
|
||||
// Loop body.
|
||||
visitCodeBlock(node->getBody());
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@ -299,4 +301,4 @@ void TAllocation::checkAllocList() const
|
||||
{
|
||||
for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
|
||||
alloc->check();
|
||||
}
|
||||
}
|
||||
|
@ -297,4 +297,4 @@ protected:
|
||||
TPoolAllocator& allocator;
|
||||
};
|
||||
|
||||
#endif // _POOLALLOC_INCLUDED_
|
||||
#endif // _POOLALLOC_INCLUDED_
|
||||
|
@ -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;
|
||||
|
||||
@ -101,4 +104,4 @@ private:
|
||||
TCompiler* ConstructCompiler(ShShaderType type, ShShaderSpec spec);
|
||||
void DeleteCompiler(TCompiler*);
|
||||
|
||||
#endif // _SHHANDLE_INCLUDED_
|
||||
#endif // _SHHANDLE_INCLUDED_
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
mSurfaceSet.insert(surface);
|
||||
|
||||
return surface;
|
||||
return success(surface);
|
||||
}
|
||||
|
||||
Surface *Display::createOffscreenSurface(int width, int height, EGLConfig config)
|
||||
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);
|
||||
|
||||
Surface *surface = new Surface(this, configuration, width, height);
|
||||
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 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())
|
||||
{
|
||||
@ -440,8 +603,15 @@ EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *sha
|
||||
|
||||
void Display::destroySurface(egl::Surface *surface)
|
||||
{
|
||||
delete surface;
|
||||
mSurfaceSet.erase(surface);
|
||||
if (surface == egl::getCurrentDrawSurface() || surface == egl::getCurrentReadSurface())
|
||||
{
|
||||
surface->setPendingDestroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete surface;
|
||||
mSurfaceSet.erase(surface);
|
||||
}
|
||||
}
|
||||
|
||||
void Display::destroyContext(gl::Context *context)
|
||||
@ -449,7 +619,7 @@ 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, ¤tDisplayMode);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
|
||||
presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
|
||||
presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL);
|
||||
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,47 +61,55 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
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,55 +2008,82 @@ 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)
|
||||
{
|
||||
GLenum wrapS = texture->getWrapS();
|
||||
GLenum wrapT = texture->getWrapT();
|
||||
GLenum minFilter = texture->getMinFilter();
|
||||
GLenum magFilter = texture->getMagFilter();
|
||||
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));
|
||||
D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
|
||||
es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
|
||||
device->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
|
||||
D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
|
||||
es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2118,12 +2136,12 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case D3DERR_DRIVERINTERNALERROR:
|
||||
case D3DERR_DEVICELOST:
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return; // No sensible error to generate
|
||||
case D3DERR_DRIVERINTERNALERROR:
|
||||
case D3DERR_DEVICELOST:
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return; // No sensible error to generate
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
@ -2399,9 +2415,9 @@ void Context::clear(GLbitfield mask)
|
||||
}
|
||||
|
||||
D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
|
||||
unorm<8>(mState.colorClearValue.red),
|
||||
unorm<8>(mState.colorClearValue.green),
|
||||
unorm<8>(mState.colorClearValue.blue));
|
||||
unorm<8>(mState.colorClearValue.red),
|
||||
unorm<8>(mState.colorClearValue.green),
|
||||
unorm<8>(mState.colorClearValue.blue));
|
||||
float depth = clamp01(mState.depthClearValue);
|
||||
int stencil = mState.stencilClearValue & 0x000000FF;
|
||||
|
||||
@ -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,48 +2697,77 @@ void Context::finish()
|
||||
egl::Display *display = getDisplay();
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
IDirect3DQuery9 *occlusionQuery = NULL;
|
||||
HRESULT result;
|
||||
|
||||
HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
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 (occlusionQuery)
|
||||
IDirect3DStateBlock9 *savedState = NULL;
|
||||
result = device->CreateStateBlock(D3DSBT_ALL, &savedState);
|
||||
if (FAILED(result))
|
||||
{
|
||||
IDirect3DStateBlock9 *savedState = NULL;
|
||||
device->CreateStateBlock(D3DSBT_ALL, &savedState);
|
||||
|
||||
HRESULT result = occlusionQuery->Issue(D3DISSUE_BEGIN);
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
// Render something outside the render target
|
||||
device->SetPixelShader(NULL);
|
||||
device->SetVertexShader(NULL);
|
||||
device->SetFVF(D3DFVF_XYZRHW);
|
||||
float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
|
||||
display->startScene();
|
||||
device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
|
||||
|
||||
result = occlusionQuery->Issue(D3DISSUE_END);
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
|
||||
{
|
||||
// Keep polling, but allow other threads to do something useful first
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
ERR("CreateStateBlock failed hr=%x\n", result);
|
||||
occlusionQuery->Release();
|
||||
|
||||
if (savedState)
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
savedState->Apply();
|
||||
savedState->Release();
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
result = occlusionQuery->Issue(D3DISSUE_BEGIN);
|
||||
if (FAILED(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);
|
||||
device->SetVertexShader(NULL);
|
||||
device->SetFVF(D3DFVF_XYZRHW);
|
||||
float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
|
||||
display->startScene();
|
||||
device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
|
||||
|
||||
result = occlusionQuery->Issue(D3DISSUE_END);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("occlusionQuery->Issue(END) failed hr=%x\n", result);
|
||||
occlusionQuery->Release();
|
||||
savedState->Apply();
|
||||
savedState->Release();
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
savedState->Apply();
|
||||
savedState->Release();
|
||||
|
||||
if (result == D3DERR_DEVICELOST)
|
||||
{
|
||||
error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2731,28 +2775,35 @@ void Context::flush()
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
IDirect3DQuery9 *eventQuery = NULL;
|
||||
HRESULT result;
|
||||
|
||||
HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
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));
|
||||
|
||||
result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
||||
ERR("eventQuery->Issue(END) failed hr=%x\n", result);
|
||||
ASSERT(false);
|
||||
eventQuery->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == D3DERR_DEVICELOST)
|
||||
{
|
||||
error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
||||
eventQuery->Release();
|
||||
|
||||
if (result == D3DERR_DEVICELOST)
|
||||
{
|
||||
error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2760,49 +2811,57 @@ 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))
|
||||
{
|
||||
data[0] = last;
|
||||
data[1] = first;
|
||||
}
|
||||
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))
|
||||
{
|
||||
data[0] = last;
|
||||
data[1] = first;
|
||||
}
|
||||
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,30 +459,38 @@ 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);
|
||||
|
||||
const egl::Config *const mConfig;
|
||||
|
||||
State mState;
|
||||
State mState;
|
||||
|
||||
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;
|
||||
@ -471,8 +499,10 @@ class Context
|
||||
IndexDataManager *mIndexDataManager;
|
||||
|
||||
Blit *mBlit;
|
||||
|
||||
StreamingIndexBuffer *mClosingIB;
|
||||
|
||||
BindingPointer<Texture> mIncompleteTextures[SAMPLER_TYPE_COUNT];
|
||||
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;
|
||||
|
63
gfx/angle/src/libGLESv2/HandleAllocator.cpp
Normal file
63
gfx/angle/src/libGLESv2/HandleAllocator.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
45
gfx/angle/src/libGLESv2/HandleAllocator.h
Normal file
45
gfx/angle/src/libGLESv2/HandleAllocator.h
Normal file
@ -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_
|
404
gfx/angle/src/libGLESv2/IndexDataManager.cpp
Normal file
404
gfx/angle/src/libGLESv2/IndexDataManager.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
||||
}
|
120
gfx/angle/src/libGLESv2/IndexDataManager.h
Normal file
120
gfx/angle/src/libGLESv2/IndexDataManager.h
Normal file
@ -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)
|
||||
{
|
||||
return mSemanticIndex[attributeIndex];
|
||||
}
|
||||
|
||||
return -1;
|
||||
ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
|
||||
|
||||
return mSemanticIndex[attributeIndex];
|
||||
}
|
||||
|
||||
// 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)
|
||||
// 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)
|
||||
{
|
||||
assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
|
||||
GLuint logicalTextureUnit = -1;
|
||||
|
||||
GLint logicalTextureUnit = -1;
|
||||
|
||||
if (mSamplers[samplerIndex].active)
|
||||
switch (type)
|
||||
{
|
||||
logicalTextureUnit = mSamplers[samplerIndex].logicalTextureUnit;
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool Program::isSamplerDirty(unsigned int samplerIndex) const
|
||||
{
|
||||
if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
|
||||
switch (type)
|
||||
{
|
||||
return mSamplers[samplerIndex].dirty;
|
||||
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();
|
||||
}
|
||||
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,9 +1000,37 @@ 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;
|
||||
}
|
||||
|
||||
return 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
|
||||
@ -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]));
|
||||
|
||||
mSamplers[samplerIndex].active = true;
|
||||
mSamplers[samplerIndex].type = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? SAMPLER_CUBE : SAMPLER_2D;
|
||||
mSamplers[samplerIndex].logicalTextureUnit = 0;
|
||||
mSamplers[samplerIndex].dirty = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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,24 +2303,43 @@ 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)
|
||||
{
|
||||
mConstantTablePS->SetIntArray(device, constantPS, v, count);
|
||||
else
|
||||
{
|
||||
mConstantTablePS->SetIntArray(device, constantPS, v, count);
|
||||
}
|
||||
}
|
||||
|
||||
if (constantVS)
|
||||
{
|
||||
mConstantTableVS->SetIntArray(device, constantVS, v, count);
|
||||
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());
|
||||
mD3DFormat = texture->getD3DFormat();
|
||||
mSamples = 0;
|
||||
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,13 +280,11 @@ Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
|
||||
ASSERT(SUCCEEDED(result));
|
||||
}
|
||||
|
||||
if (mRenderTarget)
|
||||
{
|
||||
setSize(width, height);
|
||||
mFormat = format;
|
||||
mD3DFormat = requestedFormat;
|
||||
mSamples = supportedSamples;
|
||||
}
|
||||
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,25 +397,26 @@ DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
|
||||
0, FALSE, &mDepthStencil, 0);
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
error(GL_OUT_OF_MEMORY);
|
||||
HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
|
||||
0, FALSE, &mDepthStencil, 0);
|
||||
|
||||
return;
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
error(GL_OUT_OF_MEMORY);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
}
|
||||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
if (mDepthStencil)
|
||||
{
|
||||
setSize(width, height);
|
||||
mFormat = GL_DEPTH24_STENCIL8_OES;
|
||||
mD3DFormat = D3DFMT_D24S8;
|
||||
mSamples = supportedSamples;
|
||||
}
|
||||
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,9 +446,9 @@ Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(d
|
||||
{
|
||||
if (depthStencil)
|
||||
{
|
||||
mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
|
||||
// will expect one of the valid renderbuffer formats for use in
|
||||
// glRenderbufferStorage
|
||||
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,9 +456,9 @@ Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilb
|
||||
{
|
||||
if (getDepthStencil())
|
||||
{
|
||||
mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
|
||||
// will expect one of the valid renderbuffer formats for use in
|
||||
// glRenderbufferStorage
|
||||
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,13 +480,9 @@ Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuff
|
||||
{
|
||||
if (depthStencil)
|
||||
{
|
||||
mFormat = 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
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,9 +490,9 @@ Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthSten
|
||||
{
|
||||
if (getDepthStencil())
|
||||
{
|
||||
mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
|
||||
// will expect one of the valid renderbuffer formats for use in
|
||||
// glRenderbufferStorage
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class Texture;
|
||||
class Texture;
|
||||
|
||||
// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
|
||||
// is called. The specific concrete type depends on whether the internal format is
|
||||
@ -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);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user