merge m-c to devtools

This commit is contained in:
Rob Campbell 2011-05-24 14:04:56 -03:00
commit f7149b4972
132 changed files with 7973 additions and 3476 deletions

View File

@ -477,7 +477,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eSwitchAction,
eNoLiveAttr,
kNoReqStates
kNoReqStates,
eARIASelectable
},
{
"tablist",

View File

@ -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);

View File

@ -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

View File

@ -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>

View File

@ -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 \

View 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>

View File

@ -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"

View File

@ -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>

View File

@ -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@

View File

@ -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)

View File

@ -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

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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))) {

View File

@ -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

View File

@ -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() {

View File

@ -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();
}
}

View File

@ -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',

View File

@ -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);

View File

@ -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 \

View 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>

View 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>

View File

@ -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]);

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

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

View File

@ -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.

View File

@ -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();

View 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

View File

@ -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

View File

@ -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]);

View 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: ////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
/*

View 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

View 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

View 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

View File

@ -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.

View 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.

View File

@ -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.

View File

@ -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

View File

@ -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
}

View File

@ -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);
}

View File

@ -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',
],
}
},

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View 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();
}

View 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;
};

View File

@ -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;
}

View File

@ -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;

View 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;
}

View 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_

View File

@ -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

View File

@ -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_

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -297,4 +297,4 @@ protected:
TPoolAllocator& allocator;
};
#endif // _POOLALLOC_INCLUDED_
#endif // _POOLALLOC_INCLUDED_

View File

@ -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_

View File

@ -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);
}

View File

@ -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;

View File

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

View File

@ -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);
}
}

View File

@ -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_

View File

@ -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 {

View File

@ -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;

View File

@ -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 */

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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"

View File

@ -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;

View File

@ -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, &currentDisplayMode);
HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
return SUCCEEDED(result);
}
}

View File

@ -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;
};
}

View File

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

View File

@ -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;
}
}

View File

@ -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;
};
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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());
}
}
}
}

View File

@ -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;
};
}

View File

@ -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"

View File

@ -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_

View File

@ -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;

View 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);
}
}
}
}

View 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_

View 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);
}
}

View 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_

View File

@ -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"

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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
}
}

View File

@ -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);

View File

@ -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