summaryrefslogtreecommitdiffstats
path: root/libs/rs/driver
diff options
context:
space:
mode:
Diffstat (limited to 'libs/rs/driver')
-rw-r--r--libs/rs/driver/rsdAllocation.cpp423
-rw-r--r--libs/rs/driver/rsdAllocation.h95
-rw-r--r--libs/rs/driver/rsdBcc.cpp553
-rw-r--r--libs/rs/driver/rsdBcc.h70
-rw-r--r--libs/rs/driver/rsdCore.cpp287
-rw-r--r--libs/rs/driver/rsdCore.h73
-rw-r--r--libs/rs/driver/rsdFrameBuffer.cpp161
-rw-r--r--libs/rs/driver/rsdFrameBuffer.h30
-rw-r--r--libs/rs/driver/rsdGL.cpp369
-rw-r--r--libs/rs/driver/rsdGL.h84
-rw-r--r--libs/rs/driver/rsdMesh.cpp60
-rw-r--r--libs/rs/driver/rsdMesh.h32
-rw-r--r--libs/rs/driver/rsdMeshObj.cpp194
-rw-r--r--libs/rs/driver/rsdMeshObj.h63
-rw-r--r--libs/rs/driver/rsdProgram.cpp108
-rw-r--r--libs/rs/driver/rsdProgramFragment.h32
-rw-r--r--libs/rs/driver/rsdProgramRaster.cpp55
-rw-r--r--libs/rs/driver/rsdProgramRaster.h31
-rw-r--r--libs/rs/driver/rsdProgramStore.cpp204
-rw-r--r--libs/rs/driver/rsdProgramStore.h31
-rw-r--r--libs/rs/driver/rsdProgramVertex.h31
-rw-r--r--libs/rs/driver/rsdRuntime.h29
-rw-r--r--libs/rs/driver/rsdRuntimeMath.cpp442
-rw-r--r--libs/rs/driver/rsdRuntimeStubs.cpp692
-rw-r--r--libs/rs/driver/rsdSampler.cpp40
-rw-r--r--libs/rs/driver/rsdSampler.h30
-rw-r--r--libs/rs/driver/rsdShader.cpp537
-rw-r--r--libs/rs/driver/rsdShader.h105
-rw-r--r--libs/rs/driver/rsdShaderCache.cpp283
-rw-r--r--libs/rs/driver/rsdShaderCache.h151
-rw-r--r--libs/rs/driver/rsdVertexArray.cpp138
-rw-r--r--libs/rs/driver/rsdVertexArray.h79
32 files changed, 5512 insertions, 0 deletions
diff --git a/libs/rs/driver/rsdAllocation.cpp b/libs/rs/driver/rsdAllocation.cpp
new file mode 100644
index 0000000..2e13e9d
--- /dev/null
+++ b/libs/rs/driver/rsdAllocation.cpp
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdBcc.h"
+#include "rsdRuntime.h"
+#include "rsdAllocation.h"
+
+#include "rsAllocation.h"
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+#include <GLES/glext.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+
+
+const static GLenum gFaceOrder[] = {
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+};
+
+
+GLenum rsdTypeToGLType(RsDataType t) {
+ switch (t) {
+ case RS_TYPE_UNSIGNED_5_6_5: return GL_UNSIGNED_SHORT_5_6_5;
+ case RS_TYPE_UNSIGNED_5_5_5_1: return GL_UNSIGNED_SHORT_5_5_5_1;
+ case RS_TYPE_UNSIGNED_4_4_4_4: return GL_UNSIGNED_SHORT_4_4_4_4;
+
+ //case RS_TYPE_FLOAT_16: return GL_HALF_FLOAT;
+ case RS_TYPE_FLOAT_32: return GL_FLOAT;
+ case RS_TYPE_UNSIGNED_8: return GL_UNSIGNED_BYTE;
+ case RS_TYPE_UNSIGNED_16: return GL_UNSIGNED_SHORT;
+ case RS_TYPE_SIGNED_8: return GL_BYTE;
+ case RS_TYPE_SIGNED_16: return GL_SHORT;
+ default: break;
+ }
+ return 0;
+}
+
+GLenum rsdKindToGLFormat(RsDataKind k) {
+ switch (k) {
+ case RS_KIND_PIXEL_L: return GL_LUMINANCE;
+ case RS_KIND_PIXEL_A: return GL_ALPHA;
+ case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
+ case RS_KIND_PIXEL_RGB: return GL_RGB;
+ case RS_KIND_PIXEL_RGBA: return GL_RGBA;
+ case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16;
+ default: break;
+ }
+ return 0;
+}
+
+
+static void Update2DTexture(const Allocation *alloc, const void *ptr, uint32_t xoff, uint32_t yoff,
+ uint32_t lod, RsAllocationCubemapFace face,
+ uint32_t w, uint32_t h) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ rsAssert(drv->textureID);
+ glBindTexture(drv->glTarget, drv->textureID);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ GLenum t = GL_TEXTURE_2D;
+ if (alloc->mHal.state.hasFaces) {
+ t = gFaceOrder[face];
+ }
+ glTexSubImage2D(t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
+}
+
+
+static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ glBindTexture(drv->glTarget, drv->textureID);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ uint32_t faceCount = 1;
+ if (alloc->mHal.state.hasFaces) {
+ faceCount = 6;
+ }
+
+ rsdGLCheckError(rsc, "Upload2DTexture 1 ");
+ for (uint32_t face = 0; face < faceCount; face ++) {
+ for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
+ const uint8_t *p = (const uint8_t *)drv->mallocPtr;
+ p += alloc->mHal.state.type->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0);
+
+ GLenum t = GL_TEXTURE_2D;
+ if (alloc->mHal.state.hasFaces) {
+ t = gFaceOrder[face];
+ }
+
+ if (isFirstUpload) {
+ glTexImage2D(t, lod, drv->glFormat,
+ alloc->mHal.state.type->getLODDimX(lod),
+ alloc->mHal.state.type->getLODDimY(lod),
+ 0, drv->glFormat, drv->glType, p);
+ } else {
+ glTexSubImage2D(t, lod, 0, 0,
+ alloc->mHal.state.type->getLODDimX(lod),
+ alloc->mHal.state.type->getLODDimY(lod),
+ drv->glFormat, drv->glType, p);
+ }
+ }
+ }
+
+ if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
+ glGenerateMipmap(drv->glTarget);
+ }
+ rsdGLCheckError(rsc, "Upload2DTexture");
+}
+
+static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ if (!drv->glType || !drv->glFormat) {
+ return;
+ }
+
+ if (!alloc->getPtr()) {
+ return;
+ }
+
+ bool isFirstUpload = false;
+
+ if (!drv->textureID) {
+ glGenTextures(1, &drv->textureID);
+ isFirstUpload = true;
+ }
+
+ Upload2DTexture(rsc, alloc, isFirstUpload);
+
+ if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
+ if (drv->mallocPtr) {
+ free(drv->mallocPtr);
+ drv->mallocPtr = NULL;
+ }
+ }
+ rsdGLCheckError(rsc, "UploadToTexture");
+}
+
+static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ if (!drv->glFormat) {
+ return;
+ }
+
+ if (!drv->renderTargetID) {
+ glGenRenderbuffers(1, &drv->renderTargetID);
+
+ if (!drv->renderTargetID) {
+ // This should generally not happen
+ LOGE("allocateRenderTarget failed to gen mRenderTargetID");
+ rsc->dumpDebug();
+ return;
+ }
+ glBindRenderbuffer(GL_RENDERBUFFER, drv->renderTargetID);
+ glRenderbufferStorage(GL_RENDERBUFFER, drv->glFormat,
+ alloc->mHal.state.dimensionX, alloc->mHal.state.dimensionY);
+ }
+ rsdGLCheckError(rsc, "AllocateRenderTarget");
+}
+
+static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ rsAssert(!alloc->mHal.state.type->getDimY());
+ rsAssert(!alloc->mHal.state.type->getDimZ());
+
+ //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
+
+ if (!drv->bufferID) {
+ glGenBuffers(1, &drv->bufferID);
+ }
+ if (!drv->bufferID) {
+ LOGE("Upload to buffer object failed");
+ drv->uploadDeferred = true;
+ return;
+ }
+ glBindBuffer(drv->glTarget, drv->bufferID);
+ glBufferData(drv->glTarget, alloc->mHal.state.type->getSizeBytes(),
+ drv->mallocPtr, GL_DYNAMIC_DRAW);
+ glBindBuffer(drv->glTarget, 0);
+ rsdGLCheckError(rsc, "UploadToBufferObject");
+}
+
+bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
+ DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
+ if (!drv) {
+ return false;
+ }
+
+ void * ptr = malloc(alloc->mHal.state.type->getSizeBytes());
+ if (!ptr) {
+ free(drv);
+ return false;
+ }
+
+ drv->glTarget = GL_NONE;
+ if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
+ if (alloc->mHal.state.hasFaces) {
+ drv->glTarget = GL_TEXTURE_CUBE_MAP;
+ } else {
+ drv->glTarget = GL_TEXTURE_2D;
+ }
+ } else {
+ if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
+ drv->glTarget = GL_ARRAY_BUFFER;
+ }
+ }
+
+ drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
+ drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
+
+
+ alloc->mHal.drvState.mallocPtr = ptr;
+ drv->mallocPtr = (uint8_t *)ptr;
+ alloc->mHal.drv = drv;
+ if (forceZero) {
+ memset(ptr, 0, alloc->mHal.state.type->getSizeBytes());
+ }
+
+ if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
+ drv->uploadDeferred = true;
+ }
+ return true;
+}
+
+void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ if (drv->bufferID) {
+ // Causes a SW crash....
+ //LOGV(" mBufferID %i", mBufferID);
+ //glDeleteBuffers(1, &mBufferID);
+ //mBufferID = 0;
+ }
+ if (drv->textureID) {
+ glDeleteTextures(1, &drv->textureID);
+ drv->textureID = 0;
+ }
+ if (drv->renderTargetID) {
+ glDeleteRenderbuffers(1, &drv->renderTargetID);
+ drv->renderTargetID = 0;
+ }
+
+ if (drv->mallocPtr) {
+ free(drv->mallocPtr);
+ drv->mallocPtr = NULL;
+ }
+ free(drv);
+ alloc->mHal.drv = NULL;
+}
+
+void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
+ const Type *newType, bool zeroNew) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ drv->mallocPtr = (uint8_t *)realloc(drv->mallocPtr, newType->getSizeBytes());
+
+ // fixme
+ ((Allocation *)alloc)->mHal.drvState.mallocPtr = drv->mallocPtr;
+
+ const uint32_t oldDimX = alloc->mHal.state.dimensionX;
+ const uint32_t dimX = newType->getDimX();
+
+ if (dimX > oldDimX) {
+ const Element *e = alloc->mHal.state.type->getElement();
+ uint32_t stride = e->getSizeBytes();
+ memset(((uint8_t *)drv->mallocPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
+ }
+}
+
+
+
+void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
+ RsAllocationUsageType src) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ if (!drv->uploadDeferred) {
+ return;
+ }
+
+ rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
+
+ if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
+ UploadToTexture(rsc, alloc);
+ } else {
+ if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
+ AllocateRenderTarget(rsc, alloc);
+ }
+ }
+ if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
+ UploadToBufferObject(rsc, alloc);
+ }
+
+ drv->uploadDeferred = false;
+}
+
+void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+ drv->uploadDeferred = true;
+}
+
+void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t lod, uint32_t count,
+ const void *data, uint32_t sizeBytes) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
+ uint8_t * ptr = drv->mallocPtr;
+ ptr += eSize * xoff;
+ uint32_t size = count * eSize;
+
+ if (alloc->mHal.state.hasReferences) {
+ alloc->incRefs(data, count);
+ alloc->decRefs(ptr, count);
+ }
+
+ memcpy(ptr, data, size);
+ drv->uploadDeferred = true;
+}
+
+void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
+ uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+ uint32_t lineSize = eSize * w;
+ uint32_t destW = alloc->mHal.state.dimensionX;
+
+ if (drv->mallocPtr) {
+ const uint8_t *src = static_cast<const uint8_t *>(data);
+ uint8_t *dst = drv->mallocPtr;
+ dst += alloc->mHal.state.type->getLODFaceOffset(lod, face, xoff, yoff);
+
+ for (uint32_t line=yoff; line < (yoff+h); line++) {
+ if (alloc->mHal.state.hasReferences) {
+ alloc->incRefs(src, w);
+ alloc->decRefs(dst, w);
+ }
+ memcpy(dst, src, lineSize);
+ src += lineSize;
+ dst += destW * eSize;
+ }
+ drv->uploadDeferred = true;
+ } else {
+ Update2DTexture(alloc, data, xoff, yoff, lod, face, w, h);
+ }
+}
+
+void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t zoff,
+ uint32_t lod, RsAllocationCubemapFace face,
+ uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
+
+}
+
+void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc,
+ uint32_t x,
+ const void *data, uint32_t cIdx, uint32_t sizeBytes) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+ uint8_t * ptr = drv->mallocPtr;
+ ptr += eSize * x;
+
+ const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
+ ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
+
+ if (alloc->mHal.state.hasReferences) {
+ e->incRefs(data);
+ e->decRefs(ptr);
+ }
+
+ memcpy(ptr, data, sizeBytes);
+ drv->uploadDeferred = true;
+}
+
+void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc,
+ uint32_t x, uint32_t y,
+ const void *data, uint32_t cIdx, uint32_t sizeBytes) {
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+ uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+ uint8_t * ptr = drv->mallocPtr;
+ ptr += eSize * (x + y * alloc->mHal.state.dimensionX);
+
+ const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
+ ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
+
+ if (alloc->mHal.state.hasReferences) {
+ e->incRefs(data);
+ e->decRefs(ptr);
+ }
+
+ memcpy(ptr, data, sizeBytes);
+ drv->uploadDeferred = true;
+}
+
+
diff --git a/libs/rs/driver/rsdAllocation.h b/libs/rs/driver/rsdAllocation.h
new file mode 100644
index 0000000..d7385ce
--- /dev/null
+++ b/libs/rs/driver/rsdAllocation.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_ALLOCATION_H
+#define RSD_ALLOCATION_H
+
+#include <rs_hal.h>
+#include <rsRuntime.h>
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+
+struct DrvAllocation {
+ // Is this a legal structure to be used as a texture source.
+ // Initially this will require 1D or 2D and color data
+ uint32_t textureID;
+
+ // Is this a legal structure to be used as a vertex source.
+ // Initially this will require 1D and x(yzw). Additional per element data
+ // is allowed.
+ uint32_t bufferID;
+
+ // Is this a legal structure to be used as an FBO render target
+ uint32_t renderTargetID;
+
+ uint8_t * mallocPtr;
+
+ GLenum glTarget;
+ GLenum glType;
+ GLenum glFormat;
+
+
+ bool uploadDeferred;
+};
+
+GLenum rsdTypeToGLType(RsDataType t);
+GLenum rsdKindToGLFormat(RsDataKind k);
+
+
+bool rsdAllocationInit(const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc,
+ bool forceZero);
+void rsdAllocationDestroy(const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc);
+
+void rsdAllocationResize(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ const android::renderscript::Type *newType, bool zeroNew);
+void rsdAllocationSyncAll(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ RsAllocationUsageType src);
+void rsdAllocationMarkDirty(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc);
+
+void rsdAllocationData1D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t lod, uint32_t count,
+ const void *data, uint32_t sizeBytes);
+void rsdAllocationData2D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
+ uint32_t w, uint32_t h,
+ const void *data, uint32_t sizeBytes);
+void rsdAllocationData3D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t zoff,
+ uint32_t lod, RsAllocationCubemapFace face,
+ uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes);
+
+void rsdAllocationElementData1D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t x,
+ const void *data, uint32_t elementOff, uint32_t sizeBytes);
+void rsdAllocationElementData2D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t x, uint32_t y,
+ const void *data, uint32_t elementOff, uint32_t sizeBytes);
+
+
+
+
+#endif
diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
new file mode 100644
index 0000000..8120864
--- /dev/null
+++ b/libs/rs/driver/rsdBcc.cpp
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdBcc.h"
+#include "rsdRuntime.h"
+
+#include "rsContext.h"
+#include "rsScriptC.h"
+
+#include "utils/Timers.h"
+#include "utils/StopWatch.h"
+extern "C" {
+#include "libdex/ZipArchive.h"
+}
+
+
+using namespace android;
+using namespace android::renderscript;
+
+struct DrvScript {
+ int (*mRoot)();
+ void (*mInit)();
+
+ BCCScriptRef mBccScript;
+
+ uint32_t mInvokeFunctionCount;
+ InvokeFunc_t *mInvokeFunctions;
+ uint32_t mFieldCount;
+ void ** mFieldAddress;
+ bool * mFieldIsObject;
+
+ const uint8_t * mScriptText;
+ uint32_t mScriptTextLength;
+
+ //uint32_t * mObjectSlots;
+ //uint32_t mObjectSlotCount;
+
+ uint32_t mPragmaCount;
+ const char ** mPragmaKeys;
+ const char ** mPragmaValues;
+
+};
+
+
+static Script * setTLS(Script *sc) {
+ ScriptTLSStruct * tls = (ScriptTLSStruct *)pthread_getspecific(rsdgThreadTLSKey);
+ rsAssert(tls);
+ Script *old = tls->mScript;
+ tls->mScript = sc;
+ return old;
+}
+
+
+// Input: cacheDir
+// Input: resName
+// Input: extName
+//
+// Note: cacheFile = resName + extName
+//
+// Output: Returns cachePath == cacheDir + cacheFile
+static char *genCacheFileName(const char *cacheDir,
+ const char *resName,
+ const char *extName) {
+ char cachePath[512];
+ char cacheFile[sizeof(cachePath)];
+ const size_t kBufLen = sizeof(cachePath) - 1;
+
+ cacheFile[0] = '\0';
+ // Note: resName today is usually something like
+ // "/com.android.fountain:raw/fountain"
+ if (resName[0] != '/') {
+ // Get the absolute path of the raw/***.bc file.
+
+ // Generate the absolute path. This doesn't do everything it
+ // should, e.g. if resName is "./out/whatever" it doesn't crunch
+ // the leading "./" out because this if-block is not triggered,
+ // but it'll make do.
+ //
+ if (getcwd(cacheFile, kBufLen) == NULL) {
+ LOGE("Can't get CWD while opening raw/***.bc file\n");
+ return NULL;
+ }
+ // Append "/" at the end of cacheFile so far.
+ strncat(cacheFile, "/", kBufLen);
+ }
+
+ // cacheFile = resName + extName
+ //
+ strncat(cacheFile, resName, kBufLen);
+ if (extName != NULL) {
+ // TODO(srhines): strncat() is a bit dangerous
+ strncat(cacheFile, extName, kBufLen);
+ }
+
+ // Turn the path into a flat filename by replacing
+ // any slashes after the first one with '@' characters.
+ char *cp = cacheFile + 1;
+ while (*cp != '\0') {
+ if (*cp == '/') {
+ *cp = '@';
+ }
+ cp++;
+ }
+
+ // Tack on the file name for the actual cache file path.
+ strncpy(cachePath, cacheDir, kBufLen);
+ strncat(cachePath, cacheFile, kBufLen);
+
+ LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
+ return strdup(cachePath);
+}
+
+bool rsdScriptInit(const Context *rsc,
+ ScriptC *script,
+ char const *resName,
+ char const *cacheDir,
+ uint8_t const *bitcode,
+ size_t bitcodeSize,
+ uint32_t flags) {
+ //LOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
+
+ pthread_mutex_lock(&rsdgInitMutex);
+ char *cachePath = NULL;
+ uint32_t objectSlotCount = 0;
+
+ DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
+ if (drv == NULL) {
+ goto error;
+ }
+ script->mHal.drv = drv;
+
+ drv->mBccScript = bccCreateScript();
+ script->mHal.info.isThreadable = true;
+ drv->mScriptText = bitcode;
+ drv->mScriptTextLength = bitcodeSize;
+
+ //LOGE("mBccScript %p", script->mBccScript);
+
+ if (bccRegisterSymbolCallback(drv->mBccScript, &rsdLookupRuntimeStub, script) != 0) {
+ LOGE("bcc: FAILS to register symbol callback");
+ goto error;
+ }
+
+ if (bccReadBC(drv->mBccScript,
+ resName,
+ (char const *)drv->mScriptText,
+ drv->mScriptTextLength, 0) != 0) {
+ LOGE("bcc: FAILS to read bitcode");
+ goto error;
+ }
+
+#if 1
+ if (bccLinkFile(drv->mBccScript, "/system/lib/libclcore.bc", 0) != 0) {
+ LOGE("bcc: FAILS to link bitcode");
+ goto error;
+ }
+#endif
+ cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
+
+ if (bccPrepareExecutable(drv->mBccScript, cachePath, 0) != 0) {
+ LOGE("bcc: FAILS to prepare executable");
+ goto error;
+ }
+
+ free(cachePath);
+
+ drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root"));
+ drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init"));
+
+ drv->mInvokeFunctionCount = bccGetExportFuncCount(drv->mBccScript);
+ if (drv->mInvokeFunctionCount <= 0)
+ drv->mInvokeFunctions = NULL;
+ else {
+ drv->mInvokeFunctions = (InvokeFunc_t*) calloc(drv->mInvokeFunctionCount, sizeof(InvokeFunc_t));
+ bccGetExportFuncList(drv->mBccScript, drv->mInvokeFunctionCount, (void **) drv->mInvokeFunctions);
+ }
+
+ drv->mFieldCount = bccGetExportVarCount(drv->mBccScript);
+ if (drv->mFieldCount <= 0) {
+ drv->mFieldAddress = NULL;
+ drv->mFieldIsObject = NULL;
+ } else {
+ drv->mFieldAddress = (void **) calloc(drv->mFieldCount, sizeof(void *));
+ drv->mFieldIsObject = (bool *) calloc(drv->mFieldCount, sizeof(bool));
+ bccGetExportVarList(drv->mBccScript, drv->mFieldCount, (void **) drv->mFieldAddress);
+ }
+
+ objectSlotCount = bccGetObjectSlotCount(drv->mBccScript);
+ if (objectSlotCount) {
+ uint32_t * slots = new uint32_t[objectSlotCount];
+ bccGetObjectSlotList(drv->mBccScript, objectSlotCount, slots);
+ for (uint32_t ct=0; ct < objectSlotCount; ct++) {
+ drv->mFieldIsObject[slots[ct]] = true;
+ }
+ delete [] slots;
+ }
+
+ uint32_t mPragmaCount;
+ const char ** mPragmaKeys;
+ const char ** mPragmaValues;
+
+ const static int pragmaMax = 16;
+ drv->mPragmaCount = bccGetPragmaCount(drv->mBccScript);
+ if (drv->mPragmaCount <= 0) {
+ drv->mPragmaKeys = NULL;
+ drv->mPragmaValues = NULL;
+ } else {
+ drv->mPragmaKeys = (const char **) calloc(drv->mFieldCount, sizeof(const char *));
+ drv->mPragmaValues = (const char **) calloc(drv->mFieldCount, sizeof(const char *));
+ bccGetPragmaList(drv->mBccScript, drv->mPragmaCount, drv->mPragmaKeys, drv->mPragmaValues);
+ }
+
+
+
+ // Copy info over to runtime
+ script->mHal.info.exportedFunctionCount = drv->mInvokeFunctionCount;
+ script->mHal.info.exportedVariableCount = drv->mFieldCount;
+ script->mHal.info.exportedPragmaCount = drv->mPragmaCount;
+ script->mHal.info.exportedPragmaKeyList = drv->mPragmaKeys;
+ script->mHal.info.exportedPragmaValueList = drv->mPragmaValues;
+ script->mHal.info.root = drv->mRoot;
+
+
+ pthread_mutex_unlock(&rsdgInitMutex);
+ return true;
+
+error:
+
+ pthread_mutex_unlock(&rsdgInitMutex);
+ free(drv);
+ return false;
+
+}
+
+typedef struct {
+ Context *rsc;
+ Script *script;
+ const Allocation * ain;
+ Allocation * aout;
+ const void * usr;
+
+ uint32_t mSliceSize;
+ volatile int mSliceNum;
+
+ const uint8_t *ptrIn;
+ uint32_t eStrideIn;
+ uint8_t *ptrOut;
+ uint32_t eStrideOut;
+
+ uint32_t xStart;
+ uint32_t xEnd;
+ uint32_t yStart;
+ uint32_t yEnd;
+ uint32_t zStart;
+ uint32_t zEnd;
+ uint32_t arrayStart;
+ uint32_t arrayEnd;
+
+ uint32_t dimX;
+ uint32_t dimY;
+ uint32_t dimZ;
+ uint32_t dimArray;
+} MTLaunchStruct;
+typedef int (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
+
+static void wc_xy(void *usr, uint32_t idx) {
+ MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
+
+ while (1) {
+ uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
+ uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
+ uint32_t yEnd = yStart + mtls->mSliceSize;
+ yEnd = rsMin(yEnd, mtls->yEnd);
+ if (yEnd <= yStart) {
+ return;
+ }
+
+ //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
+ //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
+ for (uint32_t y = yStart; y < yEnd; y++) {
+ uint32_t offset = mtls->dimX * y;
+ uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset);
+ const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * offset);
+
+ for (uint32_t x = mtls->xStart; x < mtls->xEnd; x++) {
+ ((rs_t)mtls->script->mHal.info.root) (xPtrIn, xPtrOut, mtls->usr, x, y, 0, 0);
+ xPtrIn += mtls->eStrideIn;
+ xPtrOut += mtls->eStrideOut;
+ }
+ }
+ }
+}
+
+static void wc_x(void *usr, uint32_t idx) {
+ MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
+
+ while (1) {
+ uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
+ uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
+ uint32_t xEnd = xStart + mtls->mSliceSize;
+ xEnd = rsMin(xEnd, mtls->xEnd);
+ if (xEnd <= xStart) {
+ return;
+ }
+
+ //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
+ //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
+ uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart);
+ const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart);
+ for (uint32_t x = xStart; x < xEnd; x++) {
+ ((rs_t)mtls->script->mHal.info.root) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0);
+ xPtrIn += mtls->eStrideIn;
+ xPtrOut += mtls->eStrideOut;
+ }
+ }
+}
+
+void rsdScriptInvokeForEach(const Context *rsc,
+ Script *s,
+ const Allocation * ain,
+ Allocation * aout,
+ const void * usr,
+ uint32_t usrLen,
+ const RsScriptCall *sc) {
+
+ RsdHal * dc = (RsdHal *)rsc->mHal.drv;
+
+ MTLaunchStruct mtls;
+ memset(&mtls, 0, sizeof(mtls));
+
+ if (ain) {
+ mtls.dimX = ain->getType()->getDimX();
+ mtls.dimY = ain->getType()->getDimY();
+ mtls.dimZ = ain->getType()->getDimZ();
+ //mtls.dimArray = ain->getType()->getDimArray();
+ } else if (aout) {
+ mtls.dimX = aout->getType()->getDimX();
+ mtls.dimY = aout->getType()->getDimY();
+ mtls.dimZ = aout->getType()->getDimZ();
+ //mtls.dimArray = aout->getType()->getDimArray();
+ } else {
+ rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
+ return;
+ }
+
+ if (!sc || (sc->xEnd == 0)) {
+ mtls.xEnd = mtls.dimX;
+ } else {
+ rsAssert(sc->xStart < mtls.dimX);
+ rsAssert(sc->xEnd <= mtls.dimX);
+ rsAssert(sc->xStart < sc->xEnd);
+ mtls.xStart = rsMin(mtls.dimX, sc->xStart);
+ mtls.xEnd = rsMin(mtls.dimX, sc->xEnd);
+ if (mtls.xStart >= mtls.xEnd) return;
+ }
+
+ if (!sc || (sc->yEnd == 0)) {
+ mtls.yEnd = mtls.dimY;
+ } else {
+ rsAssert(sc->yStart < mtls.dimY);
+ rsAssert(sc->yEnd <= mtls.dimY);
+ rsAssert(sc->yStart < sc->yEnd);
+ mtls.yStart = rsMin(mtls.dimY, sc->yStart);
+ mtls.yEnd = rsMin(mtls.dimY, sc->yEnd);
+ if (mtls.yStart >= mtls.yEnd) return;
+ }
+
+ mtls.xEnd = rsMax((uint32_t)1, mtls.xEnd);
+ mtls.yEnd = rsMax((uint32_t)1, mtls.yEnd);
+ mtls.zEnd = rsMax((uint32_t)1, mtls.zEnd);
+ mtls.arrayEnd = rsMax((uint32_t)1, mtls.arrayEnd);
+
+ rsAssert(!ain || (ain->getType()->getDimZ() == 0));
+
+ Context *mrsc = (Context *)rsc;
+ Script * oldTLS = setTLS(s);
+
+ mtls.rsc = mrsc;
+ mtls.ain = ain;
+ mtls.aout = aout;
+ mtls.script = s;
+ mtls.usr = usr;
+ mtls.mSliceSize = 10;
+ mtls.mSliceNum = 0;
+
+ mtls.ptrIn = NULL;
+ mtls.eStrideIn = 0;
+ if (ain) {
+ mtls.ptrIn = (const uint8_t *)ain->getPtr();
+ mtls.eStrideIn = ain->getType()->getElementSizeBytes();
+ }
+
+ mtls.ptrOut = NULL;
+ mtls.eStrideOut = 0;
+ if (aout) {
+ mtls.ptrOut = (uint8_t *)aout->getPtr();
+ mtls.eStrideOut = aout->getType()->getElementSizeBytes();
+ }
+
+ if ((dc->mWorkers.mCount > 1) && s->mHal.info.isThreadable) {
+ if (mtls.dimY > 1) {
+ rsdLaunchThreads(mrsc, wc_xy, &mtls);
+ } else {
+ rsdLaunchThreads(mrsc, wc_x, &mtls);
+ }
+
+ //LOGE("launch 1");
+ } else {
+ //LOGE("launch 3");
+ for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) {
+ for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) {
+ for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) {
+ uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * ar +
+ mtls.dimX * mtls.dimY * z +
+ mtls.dimX * y;
+ uint8_t *xPtrOut = mtls.ptrOut + (mtls.eStrideOut * offset);
+ const uint8_t *xPtrIn = mtls.ptrIn + (mtls.eStrideIn * offset);
+
+ for (uint32_t x = mtls.xStart; x < mtls.xEnd; x++) {
+ ((rs_t)s->mHal.info.root) (xPtrIn, xPtrOut, usr, x, y, z, ar);
+ xPtrIn += mtls.eStrideIn;
+ xPtrOut += mtls.eStrideOut;
+ }
+ }
+ }
+ }
+ }
+
+ setTLS(oldTLS);
+}
+
+
+int rsdScriptInvokeRoot(const Context *dc, Script *script) {
+ DrvScript *drv = (DrvScript *)script->mHal.drv;
+
+ Script * oldTLS = setTLS(script);
+ int ret = drv->mRoot();
+ setTLS(oldTLS);
+
+ return ret;
+}
+
+void rsdScriptInvokeInit(const Context *dc, Script *script) {
+ DrvScript *drv = (DrvScript *)script->mHal.drv;
+
+ if (drv->mInit) {
+ drv->mInit();
+ }
+}
+
+
+void rsdScriptInvokeFunction(const Context *dc, Script *script,
+ uint32_t slot,
+ const void *params,
+ size_t paramLength) {
+ DrvScript *drv = (DrvScript *)script->mHal.drv;
+ //LOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
+
+ Script * oldTLS = setTLS(script);
+ ((void (*)(const void *, uint32_t))
+ drv->mInvokeFunctions[slot])(params, paramLength);
+ setTLS(oldTLS);
+}
+
+void rsdScriptSetGlobalVar(const Context *dc, const Script *script,
+ uint32_t slot, void *data, size_t dataLength) {
+ DrvScript *drv = (DrvScript *)script->mHal.drv;
+ //rsAssert(!script->mFieldIsObject[slot]);
+ //LOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
+
+ int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot];
+ if (!destPtr) {
+ //LOGV("Calling setVar on slot = %i which is null", slot);
+ return;
+ }
+
+ memcpy(destPtr, data, dataLength);
+}
+
+void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, void *data) {
+ DrvScript *drv = (DrvScript *)script->mHal.drv;
+ //rsAssert(!script->mFieldIsObject[slot]);
+ //LOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
+
+ int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot];
+ if (!destPtr) {
+ //LOGV("Calling setVar on slot = %i which is null", slot);
+ return;
+ }
+
+ memcpy(destPtr, &data, sizeof(void *));
+}
+
+void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) {
+ DrvScript *drv = (DrvScript *)script->mHal.drv;
+ //rsAssert(script->mFieldIsObject[slot]);
+ //LOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
+
+ int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot];
+ if (!destPtr) {
+ //LOGV("Calling setVar on slot = %i which is null", slot);
+ return;
+ }
+
+ rsrSetObject(dc, script, (ObjectBase **)destPtr, data);
+}
+
+void rsdScriptDestroy(const Context *dc, Script *script) {
+ DrvScript *drv = (DrvScript *)script->mHal.drv;
+
+ if (drv->mFieldAddress) {
+ for (size_t ct=0; ct < drv->mFieldCount; ct++) {
+ if (drv->mFieldIsObject[ct]) {
+ // The field address can be NULL if the script-side has
+ // optimized the corresponding global variable away.
+ if (drv->mFieldAddress[ct]) {
+ rsrClearObject(dc, script, (ObjectBase **)drv->mFieldAddress[ct]);
+ }
+ }
+ }
+ delete [] drv->mFieldAddress;
+ delete [] drv->mFieldIsObject;
+ drv->mFieldAddress = NULL;
+ drv->mFieldIsObject = NULL;
+ drv->mFieldCount = 0;
+ }
+
+ if (drv->mInvokeFunctions) {
+ delete [] drv->mInvokeFunctions;
+ drv->mInvokeFunctions = NULL;
+ drv->mInvokeFunctionCount = 0;
+ }
+ free(drv);
+ script->mHal.drv = NULL;
+
+}
+
+
diff --git a/libs/rs/driver/rsdBcc.h b/libs/rs/driver/rsdBcc.h
new file mode 100644
index 0000000..62b50f4
--- /dev/null
+++ b/libs/rs/driver/rsdBcc.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_BCC_H
+#define RSD_BCC_H
+
+#include <rs_hal.h>
+#include <rsRuntime.h>
+
+
+bool rsdScriptInit(const android::renderscript::Context *, android::renderscript::ScriptC *,
+ char const *resName, char const *cacheDir,
+ uint8_t const *bitcode, size_t bitcodeSize, uint32_t flags);
+void rsdScriptInvokeFunction(const android::renderscript::Context *dc,
+ android::renderscript::Script *script,
+ uint32_t slot,
+ const void *params,
+ size_t paramLength);
+
+void rsdScriptInvokeForEach(const android::renderscript::Context *rsc,
+ android::renderscript::Script *s,
+ const android::renderscript::Allocation * ain,
+ android::renderscript::Allocation * aout,
+ const void * usr,
+ uint32_t usrLen,
+ const RsScriptCall *sc);
+
+int rsdScriptInvokeRoot(const android::renderscript::Context *dc,
+ android::renderscript::Script *script);
+void rsdScriptInvokeInit(const android::renderscript::Context *dc,
+ android::renderscript::Script *script);
+
+void rsdScriptSetGlobalVar(const android::renderscript::Context *,
+ const android::renderscript::Script *,
+ uint32_t slot, void *data, size_t dataLen);
+void rsdScriptSetGlobalBind(const android::renderscript::Context *,
+ const android::renderscript::Script *,
+ uint32_t slot, void *data);
+void rsdScriptSetGlobalObj(const android::renderscript::Context *,
+ const android::renderscript::Script *,
+ uint32_t slot, android::renderscript::ObjectBase *data);
+
+void rsdScriptSetGlobal(const android::renderscript::Context *dc,
+ const android::renderscript::Script *script,
+ uint32_t slot,
+ void *data,
+ size_t dataLength);
+void rsdScriptGetGlobal(const android::renderscript::Context *dc,
+ const android::renderscript::Script *script,
+ uint32_t slot,
+ void *data,
+ size_t dataLength);
+void rsdScriptDestroy(const android::renderscript::Context *dc,
+ android::renderscript::Script *script);
+
+
+#endif
diff --git a/libs/rs/driver/rsdCore.cpp b/libs/rs/driver/rsdCore.cpp
new file mode 100644
index 0000000..01cc369
--- /dev/null
+++ b/libs/rs/driver/rsdCore.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsdCore.h"
+#include "rsdAllocation.h"
+#include "rsdBcc.h"
+#include "rsdGL.h"
+#include "rsdProgramStore.h"
+#include "rsdProgramRaster.h"
+#include "rsdProgramVertex.h"
+#include "rsdProgramFragment.h"
+#include "rsdMesh.h"
+#include "rsdSampler.h"
+#include "rsdFrameBuffer.h"
+
+#include <malloc.h>
+#include "rsContext.h"
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sched.h>
+#include <cutils/properties.h>
+#include <cutils/sched_policy.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <bcc/bcc.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+static void Shutdown(Context *rsc);
+static void SetPriority(const Context *rsc, int32_t priority);
+
+static RsdHalFunctions FunctionTable = {
+ rsdGLInit,
+ rsdGLShutdown,
+ rsdGLSetSurface,
+ rsdGLSwap,
+
+ Shutdown,
+ NULL,
+ SetPriority,
+ {
+ rsdScriptInit,
+ rsdScriptInvokeFunction,
+ rsdScriptInvokeRoot,
+ rsdScriptInvokeForEach,
+ rsdScriptInvokeInit,
+ rsdScriptSetGlobalVar,
+ rsdScriptSetGlobalBind,
+ rsdScriptSetGlobalObj,
+ rsdScriptDestroy
+ },
+
+ {
+ rsdAllocationInit,
+ rsdAllocationDestroy,
+ rsdAllocationResize,
+ rsdAllocationSyncAll,
+ rsdAllocationMarkDirty,
+ rsdAllocationData1D,
+ rsdAllocationData2D,
+ rsdAllocationData3D,
+ rsdAllocationElementData1D,
+ rsdAllocationElementData2D
+ },
+
+
+ {
+ rsdProgramStoreInit,
+ rsdProgramStoreSetActive,
+ rsdProgramStoreDestroy
+ },
+
+ {
+ rsdProgramRasterInit,
+ rsdProgramRasterSetActive,
+ rsdProgramRasterDestroy
+ },
+
+ {
+ rsdProgramVertexInit,
+ rsdProgramVertexSetActive,
+ rsdProgramVertexDestroy
+ },
+
+ {
+ rsdProgramFragmentInit,
+ rsdProgramFragmentSetActive,
+ rsdProgramFragmentDestroy
+ },
+
+ {
+ rsdMeshInit,
+ rsdMeshDraw,
+ rsdMeshDestroy
+ },
+
+ {
+ rsdSamplerInit,
+ rsdSamplerDestroy
+ },
+
+ {
+ rsdFrameBufferInit,
+ rsdFrameBufferSetActive,
+ rsdFrameBufferDestroy
+ },
+
+};
+
+pthread_key_t rsdgThreadTLSKey = 0;
+uint32_t rsdgThreadTLSKeyCount = 0;
+pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void * HelperThreadProc(void *vrsc) {
+ Context *rsc = static_cast<Context *>(vrsc);
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+
+ uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount);
+
+ //LOGV("RS helperThread starting %p idx=%i", rsc, idx);
+
+ dc->mWorkers.mLaunchSignals[idx].init();
+ dc->mWorkers.mNativeThreadId[idx] = gettid();
+
+ int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
+ if (status) {
+ LOGE("pthread_setspecific %i", status);
+ }
+
+#if 0
+ typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
+ cpu_set_t cpuset;
+ memset(&cpuset, 0, sizeof(cpuset));
+ cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
+ int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
+ sizeof(cpuset), &cpuset);
+ LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
+#endif
+
+ while (!dc->mExit) {
+ dc->mWorkers.mLaunchSignals[idx].wait();
+ if (dc->mWorkers.mLaunchCallback) {
+ dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx);
+ }
+ android_atomic_dec(&dc->mWorkers.mRunningCount);
+ dc->mWorkers.mCompleteSignal.set();
+ }
+
+ //LOGV("RS helperThread exited %p idx=%i", rsc, idx);
+ return NULL;
+}
+
+void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ dc->mWorkers.mLaunchData = data;
+ dc->mWorkers.mLaunchCallback = cbk;
+ android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
+ for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
+ dc->mWorkers.mLaunchSignals[ct].set();
+ }
+ while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
+ dc->mWorkers.mCompleteSignal.wait();
+ }
+}
+
+bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) {
+ rsc->mHal.funcs = FunctionTable;
+
+ RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal));
+ if (!dc) {
+ LOGE("Calloc for driver hal failed.");
+ return false;
+ }
+ rsc->mHal.drv = dc;
+
+ pthread_mutex_lock(&rsdgInitMutex);
+ if (!rsdgThreadTLSKeyCount) {
+ int status = pthread_key_create(&rsdgThreadTLSKey, NULL);
+ if (status) {
+ LOGE("Failed to init thread tls key.");
+ pthread_mutex_unlock(&rsdgInitMutex);
+ return false;
+ }
+ }
+ rsdgThreadTLSKeyCount++;
+ pthread_mutex_unlock(&rsdgInitMutex);
+
+ dc->mTlsStruct.mContext = rsc;
+ dc->mTlsStruct.mScript = NULL;
+ int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
+ if (status) {
+ LOGE("pthread_setspecific %i", status);
+ }
+
+
+ int cpu = sysconf(_SC_NPROCESSORS_ONLN);
+ LOGV("RS Launching thread(s), reported CPU count %i", cpu);
+ if (cpu < 2) cpu = 0;
+
+ dc->mWorkers.mCount = (uint32_t)cpu;
+ dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
+ dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t));
+ dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount];
+ dc->mWorkers.mLaunchCallback = NULL;
+
+ dc->mWorkers.mCompleteSignal.init();
+
+ android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
+ android_atomic_release_store(0, &dc->mWorkers.mLaunchCount);
+
+ pthread_attr_t threadAttr;
+ status = pthread_attr_init(&threadAttr);
+ if (status) {
+ LOGE("Failed to init thread attribute.");
+ return false;
+ }
+
+ for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
+ status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc);
+ if (status) {
+ dc->mWorkers.mCount = ct;
+ LOGE("Created fewer than expected number of RS threads.");
+ break;
+ }
+ }
+ while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
+ usleep(100);
+ }
+
+ pthread_attr_destroy(&threadAttr);
+ return true;
+}
+
+
+void SetPriority(const Context *rsc, int32_t priority) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
+ setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
+ }
+}
+
+void Shutdown(Context *rsc) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ dc->mExit = true;
+ dc->mWorkers.mLaunchData = NULL;
+ dc->mWorkers.mLaunchCallback = NULL;
+ android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
+ for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
+ dc->mWorkers.mLaunchSignals[ct].set();
+ }
+ int status;
+ void *res;
+ for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
+ status = pthread_join(dc->mWorkers.mThreadId[ct], &res);
+ }
+ rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
+
+ // Global structure cleanup.
+ pthread_mutex_lock(&rsdgInitMutex);
+ --rsdgThreadTLSKeyCount;
+ if (!rsdgThreadTLSKeyCount) {
+ pthread_key_delete(rsdgThreadTLSKey);
+ }
+ pthread_mutex_unlock(&rsdgInitMutex);
+
+}
+
+
diff --git a/libs/rs/driver/rsdCore.h b/libs/rs/driver/rsdCore.h
new file mode 100644
index 0000000..f393b60
--- /dev/null
+++ b/libs/rs/driver/rsdCore.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_CORE_H
+#define RSD_CORE_H
+
+#include <rs_hal.h>
+
+#include "rsMutex.h"
+#include "rsSignal.h"
+
+#include "rsdGL.h"
+
+typedef void (* InvokeFunc_t)(void);
+typedef void (*WorkerCallback_t)(void *usr, uint32_t idx);
+
+typedef struct RsdSymbolTableRec {
+ const char * mName;
+ void * mPtr;
+ bool threadable;
+} RsdSymbolTable;
+
+typedef struct ScriptTLSStructRec {
+ android::renderscript::Context * mContext;
+ android::renderscript::Script * mScript;
+} ScriptTLSStruct;
+
+typedef struct RsdHalRec {
+ uint32_t version_major;
+ uint32_t version_minor;
+
+ struct Workers {
+ volatile int mRunningCount;
+ volatile int mLaunchCount;
+ uint32_t mCount;
+ pthread_t *mThreadId;
+ pid_t *mNativeThreadId;
+ android::renderscript::Signal mCompleteSignal;
+
+ android::renderscript::Signal *mLaunchSignals;
+ WorkerCallback_t mLaunchCallback;
+ void *mLaunchData;
+ };
+ Workers mWorkers;
+ bool mExit;
+
+ ScriptTLSStruct mTlsStruct;
+
+ RsdGL gl;
+} RsdHal;
+
+extern pthread_key_t rsdgThreadTLSKey;
+extern uint32_t rsdgThreadTLSKeyCount;
+extern pthread_mutex_t rsdgInitMutex;
+
+
+void rsdLaunchThreads(android::renderscript::Context *rsc, WorkerCallback_t cbk, void *data);
+
+#endif
+
diff --git a/libs/rs/driver/rsdFrameBuffer.cpp b/libs/rs/driver/rsdFrameBuffer.cpp
new file mode 100644
index 0000000..ce72b5d
--- /dev/null
+++ b/libs/rs/driver/rsdFrameBuffer.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdFrameBuffer.h"
+#include "rsdAllocation.h"
+
+#include "rsContext.h"
+#include "rsFBOCache.h"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+struct DrvFrameBuffer {
+ GLuint mFBOId;
+};
+
+void checkError(const Context *rsc) {
+ GLenum status;
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ switch (status) {
+ case GL_FRAMEBUFFER_COMPLETE:
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
+ break;
+ }
+}
+
+
+void setDepthAttachment(const Context *rsc, const FBOCache *fb) {
+ if (fb->mHal.state.depthTarget.get() != NULL) {
+ DrvAllocation *drv = (DrvAllocation *)fb->mHal.state.depthTarget->mHal.drv;
+
+ if (drv->textureID) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D, drv->textureID, 0);
+ } else {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, drv->renderTargetID);
+ }
+ } else {
+ // Reset last attachment
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+ }
+}
+
+void setColorAttachment(const Context *rsc, const FBOCache *fb) {
+ // Now attach color targets
+ for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
+ uint32_t texID = 0;
+ if (fb->mHal.state.colorTargets[i].get() != NULL) {
+ DrvAllocation *drv = (DrvAllocation *)fb->mHal.state.colorTargets[i]->mHal.drv;
+
+ if (drv->textureID) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_TEXTURE_2D, drv->textureID, 0);
+ } else {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_RENDERBUFFER, drv->renderTargetID);
+ }
+ } else {
+ // Reset last attachment
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_RENDERBUFFER, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_TEXTURE_2D, 0, 0);
+ }
+ }
+}
+
+bool renderToFramebuffer(const FBOCache *fb) {
+ if (fb->mHal.state.depthTarget.get() != NULL) {
+ return false;
+ }
+
+ for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
+ if (fb->mHal.state.colorTargets[i].get() != NULL) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+bool rsdFrameBufferInit(const Context *rsc, const FBOCache *fb) {
+ DrvFrameBuffer *drv = (DrvFrameBuffer *)calloc(1, sizeof(DrvFrameBuffer));
+ if (drv == NULL) {
+ return false;
+ }
+ fb->mHal.drv = drv;
+ drv->mFBOId = 0;
+
+ return true;
+}
+
+void rsdFrameBufferSetActive(const Context *rsc, const FBOCache *fb) {
+ DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
+
+ bool framebuffer = renderToFramebuffer(fb);
+ if (!framebuffer) {
+ if(drv->mFBOId == 0) {
+ glGenFramebuffers(1, &drv->mFBOId);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, drv->mFBOId);
+
+ setDepthAttachment(rsc, fb);
+ setColorAttachment(rsc, fb);
+
+ glViewport(0, 0, fb->mHal.state.colorTargets[0]->getType()->getDimX(),
+ fb->mHal.state.colorTargets[0]->getType()->getDimY());
+
+ checkError(rsc);
+ } else {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
+ }
+}
+
+void rsdFrameBufferDestroy(const Context *rsc, const FBOCache *fb) {
+ DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
+ if(drv->mFBOId != 0) {
+ glDeleteFramebuffers(1, &drv->mFBOId);
+ }
+
+ free(fb->mHal.drv);
+ fb->mHal.drv = NULL;
+}
+
+
diff --git a/libs/rs/driver/rsdFrameBuffer.h b/libs/rs/driver/rsdFrameBuffer.h
new file mode 100644
index 0000000..dec59fc
--- /dev/null
+++ b/libs/rs/driver/rsdFrameBuffer.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_FRAME_BUFFER_H
+#define RSD_FRAME_BUFFER_H
+
+#include <rs_hal.h>
+
+bool rsdFrameBufferInit(const android::renderscript::Context *rsc,
+ const android::renderscript::FBOCache *fb);
+void rsdFrameBufferSetActive(const android::renderscript::Context *rsc,
+ const android::renderscript::FBOCache *fb);
+void rsdFrameBufferDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::FBOCache *fb);
+
+
+#endif // RSD_FRAME_BUFFER_H
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
new file mode 100644
index 0000000..a70589b
--- /dev/null
+++ b/libs/rs/driver/rsdGL.cpp
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/PixelFormat.h>
+#include <ui/EGLUtils.h>
+#include <ui/egl/android_natives.h>
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sched.h>
+
+#include <cutils/properties.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <string.h>
+
+#include "rsdCore.h"
+#include "rsdGL.h"
+
+#include <malloc.h>
+#include "rsContext.h"
+#include "rsdShaderCache.h"
+#include "rsdVertexArray.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+static int32_t gGLContextCount = 0;
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+ if (returnVal != EGL_TRUE) {
+ fprintf(stderr, "%s() returned %d\n", op, returnVal);
+ }
+
+ for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+ = eglGetError()) {
+ fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+ error);
+ }
+}
+
+static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+
+#define X(VAL) {VAL, #VAL}
+ struct {EGLint attribute; const char* name;} names[] = {
+ X(EGL_BUFFER_SIZE),
+ X(EGL_ALPHA_SIZE),
+ X(EGL_BLUE_SIZE),
+ X(EGL_GREEN_SIZE),
+ X(EGL_RED_SIZE),
+ X(EGL_DEPTH_SIZE),
+ X(EGL_STENCIL_SIZE),
+ X(EGL_CONFIG_CAVEAT),
+ X(EGL_CONFIG_ID),
+ X(EGL_LEVEL),
+ X(EGL_MAX_PBUFFER_HEIGHT),
+ X(EGL_MAX_PBUFFER_PIXELS),
+ X(EGL_MAX_PBUFFER_WIDTH),
+ X(EGL_NATIVE_RENDERABLE),
+ X(EGL_NATIVE_VISUAL_ID),
+ X(EGL_NATIVE_VISUAL_TYPE),
+ X(EGL_SAMPLES),
+ X(EGL_SAMPLE_BUFFERS),
+ X(EGL_SURFACE_TYPE),
+ X(EGL_TRANSPARENT_TYPE),
+ X(EGL_TRANSPARENT_RED_VALUE),
+ X(EGL_TRANSPARENT_GREEN_VALUE),
+ X(EGL_TRANSPARENT_BLUE_VALUE),
+ X(EGL_BIND_TO_TEXTURE_RGB),
+ X(EGL_BIND_TO_TEXTURE_RGBA),
+ X(EGL_MIN_SWAP_INTERVAL),
+ X(EGL_MAX_SWAP_INTERVAL),
+ X(EGL_LUMINANCE_SIZE),
+ X(EGL_ALPHA_MASK_SIZE),
+ X(EGL_COLOR_BUFFER_TYPE),
+ X(EGL_RENDERABLE_TYPE),
+ X(EGL_CONFORMANT),
+ };
+#undef X
+
+ for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+ EGLint value = -1;
+ EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+ EGLint error = eglGetError();
+ if (returnVal && error == EGL_SUCCESS) {
+ LOGV(" %s: %d (0x%x)", names[j].name, value, value);
+ }
+ }
+}
+
+static void DumpDebug(RsdHal *dc) {
+ LOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion);
+ LOGE(" EGL context %p surface %p, Display=%p", dc->gl.egl.context, dc->gl.egl.surface,
+ dc->gl.egl.display);
+ LOGE(" GL vendor: %s", dc->gl.gl.vendor);
+ LOGE(" GL renderer: %s", dc->gl.gl.renderer);
+ LOGE(" GL Version: %s", dc->gl.gl.version);
+ LOGE(" GL Extensions: %s", dc->gl.gl.extensions);
+ LOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion);
+
+ LOGV("MAX Textures %i, %i %i", dc->gl.gl.maxVertexTextureUnits,
+ dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits);
+ LOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs);
+ LOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors,
+ dc->gl.gl.maxFragmentUniformVectors);
+ LOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors);
+}
+
+void rsdGLShutdown(const Context *rsc) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ dc->gl.shaderCache->cleanupAll();
+ delete dc->gl.shaderCache;
+
+ delete dc->gl.vertexArrayState;
+
+ LOGV("%p, deinitEGL", rsc);
+
+ if (dc->gl.egl.context != EGL_NO_CONTEXT) {
+ eglMakeCurrent(dc->gl.egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surfaceDefault);
+ if (dc->gl.egl.surface != EGL_NO_SURFACE) {
+ eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
+ }
+ eglDestroyContext(dc->gl.egl.display, dc->gl.egl.context);
+ checkEglError("eglDestroyContext");
+ }
+
+ gGLContextCount--;
+ if (!gGLContextCount) {
+ eglTerminate(dc->gl.egl.display);
+ }
+}
+
+bool rsdGLInit(const Context *rsc) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ dc->gl.egl.numConfigs = -1;
+ EGLint configAttribs[128];
+ EGLint *configAttribsPtr = configAttribs;
+ EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+
+ memset(configAttribs, 0, sizeof(configAttribs));
+
+ configAttribsPtr[0] = EGL_SURFACE_TYPE;
+ configAttribsPtr[1] = EGL_WINDOW_BIT;
+ configAttribsPtr += 2;
+
+ configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
+ configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
+ configAttribsPtr += 2;
+
+ if (rsc->mUserSurfaceConfig.depthMin > 0) {
+ configAttribsPtr[0] = EGL_DEPTH_SIZE;
+ configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
+ configAttribsPtr += 2;
+ }
+
+ if (rsc->mDev->mForceSW) {
+ configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
+ configAttribsPtr[1] = EGL_SLOW_CONFIG;
+ configAttribsPtr += 2;
+ }
+
+ configAttribsPtr[0] = EGL_NONE;
+ rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
+
+ LOGV("%p initEGL start", rsc);
+ dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ checkEglError("eglGetDisplay");
+
+ eglInitialize(dc->gl.egl.display, &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
+ checkEglError("eglInitialize");
+
+ PixelFormat pf = PIXEL_FORMAT_RGBA_8888;
+ if (rsc->mUserSurfaceConfig.alphaMin == 0) {
+ pf = PIXEL_FORMAT_RGBX_8888;
+ }
+
+ status_t err = EGLUtils::selectConfigForPixelFormat(dc->gl.egl.display, configAttribs,
+ pf, &dc->gl.egl.config);
+ if (err) {
+ LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
+ }
+ //if (props.mLogVisual) {
+ if (0) {
+ printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
+ }
+ //}
+
+ dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config,
+ EGL_NO_CONTEXT, context_attribs2);
+ checkEglError("eglCreateContext");
+ if (dc->gl.egl.context == EGL_NO_CONTEXT) {
+ LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc);
+ return false;
+ }
+ gGLContextCount++;
+
+
+ EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+ dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config,
+ pbuffer_attribs);
+ checkEglError("eglCreatePbufferSurface");
+ if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
+ LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE");
+ rsdGLShutdown(rsc);
+ return false;
+ }
+
+ EGLBoolean ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
+ dc->gl.egl.surfaceDefault, dc->gl.egl.context);
+ if (ret == EGL_FALSE) {
+ LOGE("eglMakeCurrent returned EGL_FALSE");
+ checkEglError("eglMakeCurrent", ret);
+ rsdGLShutdown(rsc);
+ return false;
+ }
+
+ dc->gl.gl.version = glGetString(GL_VERSION);
+ dc->gl.gl.vendor = glGetString(GL_VENDOR);
+ dc->gl.gl.renderer = glGetString(GL_RENDERER);
+ dc->gl.gl.extensions = glGetString(GL_EXTENSIONS);
+
+ //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
+ //LOGV("GL Version %s", mGL.mVersion);
+ //LOGV("GL Vendor %s", mGL.mVendor);
+ //LOGV("GL Renderer %s", mGL.mRenderer);
+ //LOGV("GL Extensions %s", mGL.mExtensions);
+
+ const char *verptr = NULL;
+ if (strlen((const char *)dc->gl.gl.version) > 9) {
+ if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) {
+ verptr = (const char *)dc->gl.gl.version + 12;
+ }
+ if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) {
+ verptr = (const char *)dc->gl.gl.version + 9;
+ }
+ }
+
+ if (!verptr) {
+ LOGE("Error, OpenGL ES Lite not supported");
+ rsdGLShutdown(rsc);
+ return false;
+ } else {
+ sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion);
+ }
+
+ glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs);
+ glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors);
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits);
+
+ glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors);
+ glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits);
+
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits);
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors);
+
+ dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
+ "GL_OES_texture_npot");
+ dc->gl.gl.GL_IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
+ "GL_IMG_texture_npot");
+ dc->gl.gl.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions,
+ "GL_NV_texture_npot_2D_mipmap");
+ dc->gl.gl.EXT_texture_max_aniso = 1.0f;
+ bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions,
+ "GL_EXT_texture_filter_anisotropic");
+ if (hasAniso) {
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso);
+ }
+
+ if (0) {
+ DumpDebug(dc);
+ }
+
+ dc->gl.shaderCache = new RsdShaderCache();
+ dc->gl.vertexArrayState = new RsdVertexArrayState();
+ dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
+
+ LOGV("initGLThread end %p", rsc);
+ return true;
+}
+
+
+bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ EGLBoolean ret;
+ // WAR: Some drivers fail to handle 0 size surfaces correcntly.
+ // Use the pbuffer to avoid this pitfall.
+ if ((dc->gl.egl.surface != NULL) || (w == 0) || (h == 0)) {
+ ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
+ dc->gl.egl.surfaceDefault, dc->gl.egl.context);
+ checkEglError("eglMakeCurrent", ret);
+
+ ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
+ checkEglError("eglDestroySurface", ret);
+
+ dc->gl.egl.surface = NULL;
+ dc->gl.width = 1;
+ dc->gl.height = 1;
+ }
+
+ dc->gl.wndSurface = (ANativeWindow *)sur;
+ if (dc->gl.wndSurface != NULL) {
+ dc->gl.width = w;
+ dc->gl.height = h;
+
+ dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
+ dc->gl.wndSurface, NULL);
+ checkEglError("eglCreateWindowSurface");
+ if (dc->gl.egl.surface == EGL_NO_SURFACE) {
+ LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
+ }
+
+ ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface,
+ dc->gl.egl.surface, dc->gl.egl.context);
+ checkEglError("eglMakeCurrent", ret);
+ }
+ return true;
+}
+
+void rsdGLSwap(const android::renderscript::Context *rsc) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ eglSwapBuffers(dc->gl.egl.display, dc->gl.egl.surface);
+}
+
+void rsdGLCheckError(const android::renderscript::Context *rsc,
+ const char *msg, bool isFatal) {
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR) {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg);
+
+ if (isFatal) {
+ rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
+ } else {
+ switch (err) {
+ case GL_OUT_OF_MEMORY:
+ rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf);
+ break;
+ default:
+ rsc->setError(RS_ERROR_DRIVER, buf);
+ break;
+ }
+ }
+
+ LOGE("%p, %s", rsc, buf);
+ }
+
+}
diff --git a/libs/rs/driver/rsdGL.h b/libs/rs/driver/rsdGL.h
new file mode 100644
index 0000000..01c8438
--- /dev/null
+++ b/libs/rs/driver/rsdGL.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_GL_H
+#define RSD_GL_H
+
+#include <rs_hal.h>
+#include <EGL/egl.h>
+
+class RsdShaderCache;
+class RsdVertexArrayState;
+
+typedef void (* InvokeFunc_t)(void);
+typedef void (*WorkerCallback_t)(void *usr, uint32_t idx);
+
+typedef struct RsdGLRec {
+ struct {
+ EGLint numConfigs;
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EGLConfig config;
+ EGLContext context;
+ EGLSurface surface;
+ EGLSurface surfaceDefault;
+ EGLDisplay display;
+ } egl;
+
+ struct {
+ const uint8_t * vendor;
+ const uint8_t * renderer;
+ const uint8_t * version;
+ const uint8_t * extensions;
+
+ uint32_t majorVersion;
+ uint32_t minorVersion;
+
+ int32_t maxVaryingVectors;
+ int32_t maxTextureImageUnits;
+
+ int32_t maxFragmentTextureImageUnits;
+ int32_t maxFragmentUniformVectors;
+
+ int32_t maxVertexAttribs;
+ int32_t maxVertexUniformVectors;
+ int32_t maxVertexTextureUnits;
+
+ bool OES_texture_npot;
+ bool GL_IMG_texture_npot;
+ bool GL_NV_texture_npot_2D_mipmap;
+ float EXT_texture_max_aniso;
+ } gl;
+
+ ANativeWindow *wndSurface;
+ uint32_t width;
+ uint32_t height;
+ RsdShaderCache *shaderCache;
+ RsdVertexArrayState *vertexArrayState;
+} RsdGL;
+
+
+
+bool rsdGLInit(const android::renderscript::Context *rsc);
+void rsdGLShutdown(const android::renderscript::Context *rsc);
+bool rsdGLSetSurface(const android::renderscript::Context *rsc,
+ uint32_t w, uint32_t h, RsNativeWindow sur);
+void rsdGLSwap(const android::renderscript::Context *rsc);
+void rsdGLCheckError(const android::renderscript::Context *rsc,
+ const char *msg, bool isFatal = false);
+
+#endif
+
diff --git a/libs/rs/driver/rsdMesh.cpp b/libs/rs/driver/rsdMesh.cpp
new file mode 100644
index 0000000..eb62ddb
--- /dev/null
+++ b/libs/rs/driver/rsdMesh.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <rs_hal.h>
+#include <rsContext.h>
+#include <rsMesh.h>
+
+#include "rsdCore.h"
+#include "rsdMesh.h"
+#include "rsdMeshObj.h"
+#include "rsdShaderCache.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+bool rsdMeshInit(const Context *rsc, const Mesh *m) {
+ RsdMeshObj *drv = NULL;
+ if(m->mHal.drv) {
+ drv = (RsdMeshObj*)m->mHal.drv;
+ delete drv;
+ }
+ drv = new RsdMeshObj(rsc, m);
+ m->mHal.drv = drv;
+ return drv->init();
+}
+
+void rsdMeshDraw(const Context *rsc, const Mesh *m, uint32_t primIndex, uint32_t start, uint32_t len) {
+ if(m->mHal.drv) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ if (!dc->gl.shaderCache->setup(rsc)) {
+ return;
+ }
+
+ RsdMeshObj *drv = (RsdMeshObj*)m->mHal.drv;
+ drv->renderPrimitiveRange(rsc, primIndex, start, len);
+ }
+}
+
+void rsdMeshDestroy(const Context *rsc, const Mesh *m) {
+ if(m->mHal.drv) {
+ RsdMeshObj *drv = (RsdMeshObj*)m->mHal.drv;
+ delete drv;
+ }
+}
+
+
diff --git a/libs/rs/driver/rsdMesh.h b/libs/rs/driver/rsdMesh.h
new file mode 100644
index 0000000..d2714fd
--- /dev/null
+++ b/libs/rs/driver/rsdMesh.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_MESH_H
+#define RSD_MESH_H
+
+#include <rs_hal.h>
+
+
+bool rsdMeshInit(const android::renderscript::Context *rsc,
+ const android::renderscript::Mesh *m);
+void rsdMeshDraw(const android::renderscript::Context *rsc,
+ const android::renderscript::Mesh *m,
+ uint32_t primIndex, uint32_t start, uint32_t len);
+void rsdMeshDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::Mesh *m);
+
+
+#endif
diff --git a/libs/rs/driver/rsdMeshObj.cpp b/libs/rs/driver/rsdMeshObj.cpp
new file mode 100644
index 0000000..c220ac1
--- /dev/null
+++ b/libs/rs/driver/rsdMeshObj.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+#include <GLES/glext.h>
+
+#include <rs_hal.h>
+#include <rsContext.h>
+#include <rsMesh.h>
+
+#include "rsdAllocation.h"
+#include "rsdMeshObj.h"
+#include "rsdGL.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+RsdMeshObj::RsdMeshObj(const Context *rsc, const Mesh *rsMesh) {
+ mRSMesh = rsMesh;
+
+ mAttribs = NULL;
+ mAttribAllocationIndex = NULL;
+ mGLPrimitives = NULL;
+
+ mAttribCount = 0;
+}
+
+RsdMeshObj::~RsdMeshObj() {
+ if (mAttribs) {
+ delete[] mAttribs;
+ delete[] mAttribAllocationIndex;
+ }
+ if (mGLPrimitives) {
+ delete[] mGLPrimitives;
+ }
+}
+
+bool RsdMeshObj::isValidGLComponent(const Element *elem, uint32_t fieldIdx) {
+ // Do not create attribs for padding
+ if (elem->getFieldName(fieldIdx)[0] == '#') {
+ return false;
+ }
+
+ // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
+ // Filter rs types accordingly
+ RsDataType dt = elem->getField(fieldIdx)->getComponent().getType();
+ if (dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
+ dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
+ dt != RS_TYPE_SIGNED_16) {
+ return false;
+ }
+
+ // Now make sure they are not arrays
+ uint32_t arraySize = elem->getFieldArraySize(fieldIdx);
+ if (arraySize != 1) {
+ return false;
+ }
+
+ return true;
+}
+
+bool RsdMeshObj::init() {
+
+ updateGLPrimitives();
+
+ // Count the number of gl attrs to initialize
+ mAttribCount = 0;
+ for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
+ const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
+ for (uint32_t ct=0; ct < elem->getFieldCount(); ct++) {
+ if (isValidGLComponent(elem, ct)) {
+ mAttribCount ++;
+ }
+ }
+ }
+
+ if (mAttribs) {
+ delete [] mAttribs;
+ delete [] mAttribAllocationIndex;
+ mAttribs = NULL;
+ mAttribAllocationIndex = NULL;
+ }
+ if (!mAttribCount) {
+ return false;
+ }
+
+ mAttribs = new RsdVertexArray::Attrib[mAttribCount];
+ mAttribAllocationIndex = new uint32_t[mAttribCount];
+
+ uint32_t userNum = 0;
+ for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
+ const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
+ uint32_t stride = elem->getSizeBytes();
+ for (uint32_t fieldI=0; fieldI < elem->getFieldCount(); fieldI++) {
+ const Component &c = elem->getField(fieldI)->getComponent();
+
+ if (!isValidGLComponent(elem, fieldI)) {
+ continue;
+ }
+
+ mAttribs[userNum].size = c.getVectorSize();
+ mAttribs[userNum].offset = elem->getFieldOffsetBytes(fieldI);
+ mAttribs[userNum].type = rsdTypeToGLType(c.getType());
+ mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
+ mAttribs[userNum].stride = stride;
+ String8 tmp(RS_SHADER_ATTR);
+ tmp.append(elem->getFieldName(fieldI));
+ mAttribs[userNum].name.setTo(tmp.string());
+
+ // Remember which allocation this attribute came from
+ mAttribAllocationIndex[userNum] = ct;
+ userNum ++;
+ }
+ }
+
+ return true;
+}
+
+void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
+ if (len < 1 || primIndex >= mRSMesh->mHal.state.primitivesCount || mAttribCount == 0) {
+ LOGE("Invalid mesh or parameters");
+ return;
+ }
+
+ for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
+ const Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[ct].get();
+ rsdAllocationSyncAll(rsc, alloc, RS_ALLOCATION_USAGE_SCRIPT);
+ }
+
+ // update attributes with either buffer information or data ptr based on their current state
+ for (uint32_t ct=0; ct < mAttribCount; ct++) {
+ uint32_t allocIndex = mAttribAllocationIndex[ct];
+ Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[allocIndex].get();
+ DrvAllocation *drvAlloc = (DrvAllocation *)alloc->mHal.drv;
+
+ if (drvAlloc->bufferID) {
+ mAttribs[ct].buffer = drvAlloc->bufferID;
+ mAttribs[ct].ptr = NULL;
+ } else {
+ mAttribs[ct].buffer = 0;
+ mAttribs[ct].ptr = (const uint8_t*)drvAlloc->mallocPtr;
+ }
+ }
+
+ RsdVertexArray va(mAttribs, mAttribCount);
+ va.setup(rsc);
+
+ Mesh::Primitive_t *prim = mRSMesh->mHal.state.primitives[primIndex];
+ const Allocation *idxAlloc = prim->mIndexBuffer.get();
+ if (idxAlloc) {
+ DrvAllocation *drvAlloc = (DrvAllocation *)idxAlloc->mHal.drv;
+ rsdAllocationSyncAll(rsc, idxAlloc, RS_ALLOCATION_USAGE_SCRIPT);
+
+ if (drvAlloc->bufferID) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drvAlloc->bufferID);
+ glDrawElements(mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2));
+ } else {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glDrawElements(mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT, drvAlloc->mallocPtr);
+ }
+ } else {
+ glDrawArrays(mGLPrimitives[primIndex], start, len);
+ }
+
+ rsdGLCheckError(rsc, "Mesh::renderPrimitiveRange");
+}
+
+void RsdMeshObj::updateGLPrimitives() {
+ mGLPrimitives = new uint32_t[mRSMesh->mHal.state.primitivesCount];
+ for (uint32_t i = 0; i < mRSMesh->mHal.state.primitivesCount; i ++) {
+ switch (mRSMesh->mHal.state.primitives[i]->mPrimitive) {
+ case RS_PRIMITIVE_POINT: mGLPrimitives[i] = GL_POINTS; break;
+ case RS_PRIMITIVE_LINE: mGLPrimitives[i] = GL_LINES; break;
+ case RS_PRIMITIVE_LINE_STRIP: mGLPrimitives[i] = GL_LINE_STRIP; break;
+ case RS_PRIMITIVE_TRIANGLE: mGLPrimitives[i] = GL_TRIANGLES; break;
+ case RS_PRIMITIVE_TRIANGLE_STRIP: mGLPrimitives[i] = GL_TRIANGLE_STRIP; break;
+ case RS_PRIMITIVE_TRIANGLE_FAN: mGLPrimitives[i] = GL_TRIANGLE_FAN; break;
+ }
+ }
+}
diff --git a/libs/rs/driver/rsdMeshObj.h b/libs/rs/driver/rsdMeshObj.h
new file mode 100644
index 0000000..8b1271b
--- /dev/null
+++ b/libs/rs/driver/rsdMeshObj.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RSD_MESH_OBJ_H
+#define ANDROID_RSD_MESH_OBJ_H
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+ class Context;
+ class Mesh;
+ class Element;
+
+}
+}
+
+#include "driver/rsdVertexArray.h"
+
+// An element is a group of Components that occupies one cell in a structure.
+class RsdMeshObj {
+public:
+ RsdMeshObj(const android::renderscript::Context *,
+ const android::renderscript::Mesh *);
+ ~RsdMeshObj();
+
+ void renderPrimitiveRange(const android::renderscript::Context *, uint32_t primIndex, uint32_t start, uint32_t len) const;
+
+ bool init();
+
+protected:
+ const android::renderscript::Mesh *mRSMesh;
+
+ uint32_t *mGLPrimitives;
+ void updateGLPrimitives();
+
+ bool isValidGLComponent(const android::renderscript::Element *elem, uint32_t fieldIdx);
+ // Attribues that allow us to map to GL
+ RsdVertexArray::Attrib *mAttribs;
+ // This allows us to figure out which allocation the attribute
+ // belongs to. In the event the allocation is uploaded to GL
+ // buffer, it lets us properly map it
+ uint32_t *mAttribAllocationIndex;
+ uint32_t mAttribCount;
+};
+
+#endif //ANDROID_RSD_MESH_OBJ_H
+
+
+
diff --git a/libs/rs/driver/rsdProgram.cpp b/libs/rs/driver/rsdProgram.cpp
new file mode 100644
index 0000000..39b3805
--- /dev/null
+++ b/libs/rs/driver/rsdProgram.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdAllocation.h"
+#include "rsdProgramVertex.h"
+#include "rsdShader.h"
+#include "rsdShaderCache.h"
+
+#include "rsContext.h"
+#include "rsProgramVertex.h"
+#include "rsProgramFragment.h"
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+bool rsdProgramVertexInit(const Context *rsc, const ProgramVertex *pv,
+ const char* shader, uint32_t shaderLen) {
+ RsdShader *drv = new RsdShader(pv, GL_VERTEX_SHADER, shader, shaderLen);
+ pv->mHal.drv = drv;
+
+ return drv->createShader();
+}
+
+static void SyncProgramConstants(const Context *rsc, const Program *p) {
+ for (uint32_t ct=0; ct < p->mHal.state.texturesCount; ct++) {
+ const Allocation *a = p->mHal.state.textures[ct].get();
+ DrvAllocation *drvAlloc = (DrvAllocation *)a->mHal.drv;
+ if (drvAlloc->uploadDeferred) {
+ rsdAllocationSyncAll(rsc, a, RS_ALLOCATION_USAGE_SCRIPT);
+ }
+ }
+}
+
+void rsdProgramVertexSetActive(const Context *rsc, const ProgramVertex *pv) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ SyncProgramConstants(rsc, pv);
+ dc->gl.shaderCache->setActiveVertex((RsdShader*)pv->mHal.drv);
+}
+
+void rsdProgramVertexDestroy(const Context *rsc, const ProgramVertex *pv) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ RsdShader *drv = NULL;
+ if(pv->mHal.drv) {
+ drv = (RsdShader*)pv->mHal.drv;
+ if (rsc->props.mLogShaders) {
+ LOGV("Destroying vertex shader with ID %u", drv->getShaderID());
+ }
+ if (drv->getShaderID()) {
+ dc->gl.shaderCache->cleanupVertex(drv->getShaderID());
+ }
+ delete drv;
+ }
+}
+
+bool rsdProgramFragmentInit(const Context *rsc, const ProgramFragment *pf,
+ const char* shader, uint32_t shaderLen) {
+ RsdShader *drv = new RsdShader(pf, GL_FRAGMENT_SHADER, shader, shaderLen);
+ pf->mHal.drv = drv;
+
+ return drv->createShader();
+}
+
+void rsdProgramFragmentSetActive(const Context *rsc, const ProgramFragment *pf) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ SyncProgramConstants(rsc, pf);
+ dc->gl.shaderCache->setActiveFragment((RsdShader*)pf->mHal.drv);
+}
+
+void rsdProgramFragmentDestroy(const Context *rsc, const ProgramFragment *pf) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ RsdShader *drv = NULL;
+ if(pf->mHal.drv) {
+ drv = (RsdShader*)pf->mHal.drv;
+ if (rsc->props.mLogShaders) {
+ LOGV("Destroying fragment shader with ID %u", drv->getShaderID());
+ }
+ if (drv->getShaderID()) {
+ dc->gl.shaderCache->cleanupFragment(drv->getShaderID());
+ }
+ delete drv;
+ }
+}
+
+
diff --git a/libs/rs/driver/rsdProgramFragment.h b/libs/rs/driver/rsdProgramFragment.h
new file mode 100644
index 0000000..366cb40
--- /dev/null
+++ b/libs/rs/driver/rsdProgramFragment.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_PROGRAM_FRAGMENT_H
+#define RSD_PROGRAM_FRAGMENT_H
+
+#include <rs_hal.h>
+
+
+bool rsdProgramFragmentInit(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramFragment *,
+ const char* shader, uint32_t shaderLen);
+void rsdProgramFragmentSetActive(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramFragment *);
+void rsdProgramFragmentDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramFragment *);
+
+
+#endif //RSD_PROGRAM_Fragment_H
diff --git a/libs/rs/driver/rsdProgramRaster.cpp b/libs/rs/driver/rsdProgramRaster.cpp
new file mode 100644
index 0000000..65995be
--- /dev/null
+++ b/libs/rs/driver/rsdProgramRaster.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdProgramStore.h"
+
+#include "rsContext.h"
+#include "rsProgramStore.h"
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+
+using namespace android;
+using namespace android::renderscript;
+
+bool rsdProgramRasterInit(const Context *, const ProgramRaster *) {
+ return true;
+}
+
+void rsdProgramRasterSetActive(const Context *, const ProgramRaster *pr) {
+ switch (pr->mHal.state.cull) {
+ case RS_CULL_BACK:
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ break;
+ case RS_CULL_FRONT:
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ break;
+ case RS_CULL_NONE:
+ glDisable(GL_CULL_FACE);
+ break;
+ }
+
+}
+
+void rsdProgramRasterDestroy(const Context *, const ProgramRaster *) {
+}
+
+
diff --git a/libs/rs/driver/rsdProgramRaster.h b/libs/rs/driver/rsdProgramRaster.h
new file mode 100644
index 0000000..20adaad
--- /dev/null
+++ b/libs/rs/driver/rsdProgramRaster.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_PROGRAM_RASTER_H
+#define RSD_PROGRAM_RASTER_H
+
+#include <rs_hal.h>
+
+
+bool rsdProgramRasterInit(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramRaster *);
+void rsdProgramRasterSetActive(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramRaster *);
+void rsdProgramRasterDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramRaster *);
+
+
+#endif
diff --git a/libs/rs/driver/rsdProgramStore.cpp b/libs/rs/driver/rsdProgramStore.cpp
new file mode 100644
index 0000000..e591453
--- /dev/null
+++ b/libs/rs/driver/rsdProgramStore.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdProgramStore.h"
+
+#include "rsContext.h"
+#include "rsProgramStore.h"
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+
+using namespace android;
+using namespace android::renderscript;
+
+struct DrvProgramStore {
+ GLenum blendSrc;
+ GLenum blendDst;
+ bool blendEnable;
+
+ GLenum depthFunc;
+ bool depthTestEnable;
+};
+
+bool rsdProgramStoreInit(const Context *rsc, const ProgramStore *ps) {
+ DrvProgramStore *drv = (DrvProgramStore *)calloc(1, sizeof(DrvProgramStore));
+ if (drv == NULL) {
+ return false;
+ }
+
+ ps->mHal.drv = drv;
+ drv->depthTestEnable = true;
+
+ switch (ps->mHal.state.depthFunc) {
+ case RS_DEPTH_FUNC_ALWAYS:
+ drv->depthTestEnable = false;
+ drv->depthFunc = GL_ALWAYS;
+ break;
+ case RS_DEPTH_FUNC_LESS:
+ drv->depthFunc = GL_LESS;
+ break;
+ case RS_DEPTH_FUNC_LEQUAL:
+ drv->depthFunc = GL_LEQUAL;
+ break;
+ case RS_DEPTH_FUNC_GREATER:
+ drv->depthFunc = GL_GREATER;
+ break;
+ case RS_DEPTH_FUNC_GEQUAL:
+ drv->depthFunc = GL_GEQUAL;
+ break;
+ case RS_DEPTH_FUNC_EQUAL:
+ drv->depthFunc = GL_EQUAL;
+ break;
+ case RS_DEPTH_FUNC_NOTEQUAL:
+ drv->depthFunc = GL_NOTEQUAL;
+ break;
+ default:
+ LOGE("Unknown depth function.");
+ goto error;
+ }
+
+
+
+ drv->blendEnable = true;
+ if ((ps->mHal.state.blendSrc == RS_BLEND_SRC_ONE) &&
+ (ps->mHal.state.blendDst == RS_BLEND_DST_ZERO)) {
+ drv->blendEnable = false;
+ }
+
+ switch (ps->mHal.state.blendSrc) {
+ case RS_BLEND_SRC_ZERO:
+ drv->blendSrc = GL_ZERO;
+ break;
+ case RS_BLEND_SRC_ONE:
+ drv->blendSrc = GL_ONE;
+ break;
+ case RS_BLEND_SRC_DST_COLOR:
+ drv->blendSrc = GL_DST_COLOR;
+ break;
+ case RS_BLEND_SRC_ONE_MINUS_DST_COLOR:
+ drv->blendSrc = GL_ONE_MINUS_DST_COLOR;
+ break;
+ case RS_BLEND_SRC_SRC_ALPHA:
+ drv->blendSrc = GL_SRC_ALPHA;
+ break;
+ case RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA:
+ drv->blendSrc = GL_ONE_MINUS_SRC_ALPHA;
+ break;
+ case RS_BLEND_SRC_DST_ALPHA:
+ drv->blendSrc = GL_DST_ALPHA;
+ break;
+ case RS_BLEND_SRC_ONE_MINUS_DST_ALPHA:
+ drv->blendSrc = GL_ONE_MINUS_DST_ALPHA;
+ break;
+ case RS_BLEND_SRC_SRC_ALPHA_SATURATE:
+ drv->blendSrc = GL_SRC_ALPHA_SATURATE;
+ break;
+ default:
+ LOGE("Unknown blend src mode.");
+ goto error;
+ }
+
+ switch (ps->mHal.state.blendDst) {
+ case RS_BLEND_DST_ZERO:
+ drv->blendDst = GL_ZERO;
+ break;
+ case RS_BLEND_DST_ONE:
+ drv->blendDst = GL_ONE;
+ break;
+ case RS_BLEND_DST_SRC_COLOR:
+ drv->blendDst = GL_SRC_COLOR;
+ break;
+ case RS_BLEND_DST_ONE_MINUS_SRC_COLOR:
+ drv->blendDst = GL_ONE_MINUS_SRC_COLOR;
+ break;
+ case RS_BLEND_DST_SRC_ALPHA:
+ drv->blendDst = GL_SRC_ALPHA;
+ break;
+ case RS_BLEND_DST_ONE_MINUS_SRC_ALPHA:
+ drv->blendDst = GL_ONE_MINUS_SRC_ALPHA;
+ break;
+ case RS_BLEND_DST_DST_ALPHA:
+ drv->blendDst = GL_DST_ALPHA;
+ break;
+ case RS_BLEND_DST_ONE_MINUS_DST_ALPHA:
+ drv->blendDst = GL_ONE_MINUS_DST_ALPHA;
+ break;
+ default:
+ LOGE("Unknown blend dst mode.");
+ goto error;
+ }
+
+ return true;
+
+error:
+ free(drv);
+ ps->mHal.drv = NULL;
+ return false;
+}
+
+void rsdProgramStoreSetActive(const Context *rsc, const ProgramStore *ps) {
+ DrvProgramStore *drv = (DrvProgramStore *)ps->mHal.drv;
+
+ glColorMask(ps->mHal.state.colorRWriteEnable,
+ ps->mHal.state.colorGWriteEnable,
+ ps->mHal.state.colorBWriteEnable,
+ ps->mHal.state.colorAWriteEnable);
+
+ if (drv->blendEnable) {
+ glEnable(GL_BLEND);
+ glBlendFunc(drv->blendSrc, drv->blendDst);
+ } else {
+ glDisable(GL_BLEND);
+ }
+
+ if (rsc->mUserSurfaceConfig.depthMin > 0) {
+ glDepthMask(ps->mHal.state.depthWriteEnable);
+ if (drv->depthTestEnable || ps->mHal.state.depthWriteEnable) {
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(drv->depthFunc);
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ }
+ } else {
+ glDepthMask(false);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ /*
+ if (rsc->mUserSurfaceConfig.stencilMin > 0) {
+ } else {
+ glStencilMask(0);
+ glDisable(GL_STENCIL_TEST);
+ }
+ */
+
+ if (ps->mHal.state.ditherEnable) {
+ glEnable(GL_DITHER);
+ } else {
+ glDisable(GL_DITHER);
+ }
+}
+
+void rsdProgramStoreDestroy(const Context *rsc, const ProgramStore *ps) {
+ free(ps->mHal.drv);
+ ps->mHal.drv = NULL;
+}
+
+
diff --git a/libs/rs/driver/rsdProgramStore.h b/libs/rs/driver/rsdProgramStore.h
new file mode 100644
index 0000000..217a0ce
--- /dev/null
+++ b/libs/rs/driver/rsdProgramStore.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_PROGRAM_STORE_H
+#define RSD_PROGRAM_STORE_H
+
+#include <rs_hal.h>
+
+
+bool rsdProgramStoreInit(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramStore *ps);
+void rsdProgramStoreSetActive(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramStore *ps);
+void rsdProgramStoreDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramStore *ps);
+
+
+#endif
diff --git a/libs/rs/driver/rsdProgramVertex.h b/libs/rs/driver/rsdProgramVertex.h
new file mode 100644
index 0000000..e998572
--- /dev/null
+++ b/libs/rs/driver/rsdProgramVertex.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_PROGRAM_VERTEX_H
+#define RSD_PROGRAM_VERTEX_H
+
+#include <rs_hal.h>
+
+bool rsdProgramVertexInit(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramVertex *,
+ const char* shader, uint32_t shaderLen);
+void rsdProgramVertexSetActive(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramVertex *);
+void rsdProgramVertexDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramVertex *);
+
+
+#endif //RSD_PROGRAM_VERTEX_H
diff --git a/libs/rs/driver/rsdRuntime.h b/libs/rs/driver/rsdRuntime.h
new file mode 100644
index 0000000..840eced
--- /dev/null
+++ b/libs/rs/driver/rsdRuntime.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_RUNTIME_STUBS_H
+#define RSD_RUNTIME_STUBS_H
+
+#include <rs_hal.h>
+#include <bcc/bcc.h>
+
+#include "rsMutex.h"
+
+const RsdSymbolTable * rsdLookupSymbolMath(const char *sym);
+
+void* rsdLookupRuntimeStub(void* pContext, char const* name);
+
+#endif
diff --git a/libs/rs/driver/rsdRuntimeMath.cpp b/libs/rs/driver/rsdRuntimeMath.cpp
new file mode 100644
index 0000000..acb990d
--- /dev/null
+++ b/libs/rs/driver/rsdRuntimeMath.cpp
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsScriptC.h"
+#include "rsMatrix4x4.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix2x2.h"
+
+#include "rsdCore.h"
+#include "rsdRuntime.h"
+
+
+using namespace android;
+using namespace android::renderscript;
+
+
+static float SC_exp10(float v) {
+ return pow(10.f, v);
+}
+
+static float SC_fract(float v, int *iptr) {
+ int i = (int)floor(v);
+ iptr[0] = i;
+ return fmin(v - i, 0x1.fffffep-1f);
+}
+
+static float SC_log2(float v) {
+ return log10(v) / log10(2.f);
+}
+
+static float SC_mad(float v1, float v2, float v3) {
+ return v1 * v2 + v3;
+}
+
+#if 0
+static float SC_pown(float v, int p) {
+ return powf(v, (float)p);
+}
+
+static float SC_powr(float v, float p) {
+ return powf(v, p);
+}
+#endif
+
+float SC_rootn(float v, int r) {
+ return pow(v, 1.f / r);
+}
+
+float SC_rsqrt(float v) {
+ return 1.f / sqrtf(v);
+}
+
+float SC_sincos(float v, float *cosptr) {
+ *cosptr = cosf(v);
+ return sinf(v);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Integer
+//////////////////////////////////////////////////////////////////////////////
+
+
+static uint32_t SC_abs_i32(int32_t v) {return abs(v);}
+static uint16_t SC_abs_i16(int16_t v) {return (uint16_t)abs(v);}
+static uint8_t SC_abs_i8(int8_t v) {return (uint8_t)abs(v);}
+
+static uint32_t SC_clz_u32(uint32_t v) {return __builtin_clz(v);}
+static uint16_t SC_clz_u16(uint16_t v) {return (uint16_t)__builtin_clz(v);}
+static uint8_t SC_clz_u8(uint8_t v) {return (uint8_t)__builtin_clz(v);}
+static int32_t SC_clz_i32(int32_t v) {return (int32_t)__builtin_clz((uint32_t)v);}
+static int16_t SC_clz_i16(int16_t v) {return (int16_t)__builtin_clz(v);}
+static int8_t SC_clz_i8(int8_t v) {return (int8_t)__builtin_clz(v);}
+
+static uint32_t SC_max_u32(uint32_t v, uint32_t v2) {return rsMax(v, v2);}
+static uint16_t SC_max_u16(uint16_t v, uint16_t v2) {return rsMax(v, v2);}
+static uint8_t SC_max_u8(uint8_t v, uint8_t v2) {return rsMax(v, v2);}
+static int32_t SC_max_i32(int32_t v, int32_t v2) {return rsMax(v, v2);}
+static int16_t SC_max_i16(int16_t v, int16_t v2) {return rsMax(v, v2);}
+static int8_t SC_max_i8(int8_t v, int8_t v2) {return rsMax(v, v2);}
+
+static uint32_t SC_min_u32(uint32_t v, uint32_t v2) {return rsMin(v, v2);}
+static uint16_t SC_min_u16(uint16_t v, uint16_t v2) {return rsMin(v, v2);}
+static uint8_t SC_min_u8(uint8_t v, uint8_t v2) {return rsMin(v, v2);}
+static int32_t SC_min_i32(int32_t v, int32_t v2) {return rsMin(v, v2);}
+static int16_t SC_min_i16(int16_t v, int16_t v2) {return rsMin(v, v2);}
+static int8_t SC_min_i8(int8_t v, int8_t v2) {return rsMin(v, v2);}
+
+//////////////////////////////////////////////////////////////////////////////
+// Float util
+//////////////////////////////////////////////////////////////////////////////
+
+static float SC_clamp_f32(float amount, float low, float high) {
+ return amount < low ? low : (amount > high ? high : amount);
+}
+
+static float SC_degrees(float radians) {
+ return radians * (180.f / M_PI);
+}
+
+static float SC_max_f32(float v, float v2) {
+ return rsMax(v, v2);
+}
+
+static float SC_min_f32(float v, float v2) {
+ return rsMin(v, v2);
+}
+
+static float SC_mix_f32(float start, float stop, float amount) {
+ //LOGE("lerpf %f %f %f", start, stop, amount);
+ return start + (stop - start) * amount;
+}
+
+static float SC_radians(float degrees) {
+ return degrees * (M_PI / 180.f);
+}
+
+static float SC_step_f32(float edge, float v) {
+ if (v < edge) return 0.f;
+ return 1.f;
+}
+
+static float SC_sign_f32(float value) {
+ if (value > 0) return 1.f;
+ if (value < 0) return -1.f;
+ return value;
+}
+
+static void SC_MatrixLoadIdentity_4x4(Matrix4x4 *m) {
+ m->loadIdentity();
+}
+static void SC_MatrixLoadIdentity_3x3(Matrix3x3 *m) {
+ m->loadIdentity();
+}
+static void SC_MatrixLoadIdentity_2x2(Matrix2x2 *m) {
+ m->loadIdentity();
+}
+
+static void SC_MatrixLoad_4x4_f(Matrix4x4 *m, const float *f) {
+ m->load(f);
+}
+static void SC_MatrixLoad_3x3_f(Matrix3x3 *m, const float *f) {
+ m->load(f);
+}
+static void SC_MatrixLoad_2x2_f(Matrix2x2 *m, const float *f) {
+ m->load(f);
+}
+
+static void SC_MatrixLoad_4x4_4x4(Matrix4x4 *m, const Matrix4x4 *s) {
+ m->load(s);
+}
+static void SC_MatrixLoad_4x4_3x3(Matrix4x4 *m, const Matrix3x3 *s) {
+ m->load(s);
+}
+static void SC_MatrixLoad_4x4_2x2(Matrix4x4 *m, const Matrix2x2 *s) {
+ m->load(s);
+}
+static void SC_MatrixLoad_3x3_3x3(Matrix3x3 *m, const Matrix3x3 *s) {
+ m->load(s);
+}
+static void SC_MatrixLoad_2x2_2x2(Matrix2x2 *m, const Matrix2x2 *s) {
+ m->load(s);
+}
+
+static void SC_MatrixLoadRotate(Matrix4x4 *m, float rot, float x, float y, float z) {
+ m->loadRotate(rot, x, y, z);
+}
+static void SC_MatrixLoadScale(Matrix4x4 *m, float x, float y, float z) {
+ m->loadScale(x, y, z);
+}
+static void SC_MatrixLoadTranslate(Matrix4x4 *m, float x, float y, float z) {
+ m->loadTranslate(x, y, z);
+}
+static void SC_MatrixRotate(Matrix4x4 *m, float rot, float x, float y, float z) {
+ m->rotate(rot, x, y, z);
+}
+static void SC_MatrixScale(Matrix4x4 *m, float x, float y, float z) {
+ m->scale(x, y, z);
+}
+static void SC_MatrixTranslate(Matrix4x4 *m, float x, float y, float z) {
+ m->translate(x, y, z);
+}
+
+static void SC_MatrixLoadMultiply_4x4_4x4_4x4(Matrix4x4 *m, const Matrix4x4 *lhs, const Matrix4x4 *rhs) {
+ m->loadMultiply(lhs, rhs);
+}
+static void SC_MatrixLoadMultiply_3x3_3x3_3x3(Matrix3x3 *m, const Matrix3x3 *lhs, const Matrix3x3 *rhs) {
+ m->loadMultiply(lhs, rhs);
+}
+static void SC_MatrixLoadMultiply_2x2_2x2_2x2(Matrix2x2 *m, const Matrix2x2 *lhs, const Matrix2x2 *rhs) {
+ m->loadMultiply(lhs, rhs);
+}
+
+static void SC_MatrixMultiply_4x4_4x4(Matrix4x4 *m, const Matrix4x4 *rhs) {
+ m->multiply(rhs);
+}
+static void SC_MatrixMultiply_3x3_3x3(Matrix3x3 *m, const Matrix3x3 *rhs) {
+ m->multiply(rhs);
+}
+static void SC_MatrixMultiply_2x2_2x2(Matrix2x2 *m, const Matrix2x2 *rhs) {
+ m->multiply(rhs);
+}
+
+static void SC_MatrixLoadOrtho(Matrix4x4 *m, float l, float r, float b, float t, float n, float f) {
+ m->loadOrtho(l, r, b, t, n, f);
+}
+static void SC_MatrixLoadFrustum(Matrix4x4 *m, float l, float r, float b, float t, float n, float f) {
+ m->loadFrustum(l, r, b, t, n, f);
+}
+static void SC_MatrixLoadPerspective(Matrix4x4 *m, float fovy, float aspect, float near, float far) {
+ m->loadPerspective(fovy, aspect, near, far);
+}
+
+static bool SC_MatrixInverse_4x4(Matrix4x4 *m) {
+ return m->inverse();
+}
+static bool SC_MatrixInverseTranspose_4x4(Matrix4x4 *m) {
+ return m->inverseTranspose();
+}
+static void SC_MatrixTranspose_4x4(Matrix4x4 *m) {
+ m->transpose();
+}
+static void SC_MatrixTranspose_3x3(Matrix3x3 *m) {
+ m->transpose();
+}
+static void SC_MatrixTranspose_2x2(Matrix2x2 *m) {
+ m->transpose();
+}
+
+static float SC_randf(float max) {
+ float r = (float)rand();
+ r *= max;
+ r /= RAND_MAX;
+ return r;
+}
+
+static float SC_randf2(float min, float max) {
+ float r = (float)rand();
+ r /= RAND_MAX;
+ r = r * (max - min) + min;
+ return r;
+}
+
+static int SC_randi(int max) {
+ return (int)SC_randf(max);
+}
+
+static int SC_randi2(int min, int max) {
+ return (int)SC_randf2(min, max);
+}
+
+static float SC_frac(float v) {
+ int i = (int)floor(v);
+ return fmin(v - i, 0x1.fffffep-1f);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Class implementation
+//////////////////////////////////////////////////////////////////////////////
+
+// llvm name mangling ref
+// <builtin-type> ::= v # void
+// ::= b # bool
+// ::= c # char
+// ::= a # signed char
+// ::= h # unsigned char
+// ::= s # short
+// ::= t # unsigned short
+// ::= i # int
+// ::= j # unsigned int
+// ::= l # long
+// ::= m # unsigned long
+// ::= x # long long, __int64
+// ::= y # unsigned long long, __int64
+// ::= f # float
+// ::= d # double
+
+static RsdSymbolTable gSyms[] = {
+ { "_Z4acosf", (void *)&acosf, true },
+ { "_Z5acoshf", (void *)&acoshf, true },
+ { "_Z4asinf", (void *)&asinf, true },
+ { "_Z5asinhf", (void *)&asinhf, true },
+ { "_Z4atanf", (void *)&atanf, true },
+ { "_Z5atan2ff", (void *)&atan2f, true },
+ { "_Z5atanhf", (void *)&atanhf, true },
+ { "_Z4cbrtf", (void *)&cbrtf, true },
+ { "_Z4ceilf", (void *)&ceilf, true },
+ { "_Z8copysignff", (void *)&copysignf, true },
+ { "_Z3cosf", (void *)&cosf, true },
+ { "_Z4coshf", (void *)&coshf, true },
+ { "_Z4erfcf", (void *)&erfcf, true },
+ { "_Z3erff", (void *)&erff, true },
+ { "_Z3expf", (void *)&expf, true },
+ { "_Z4exp2f", (void *)&exp2f, true },
+ { "_Z5exp10f", (void *)&SC_exp10, true },
+ { "_Z5expm1f", (void *)&expm1f, true },
+ { "_Z4fabsf", (void *)&fabsf, true },
+ { "_Z4fdimff", (void *)&fdimf, true },
+ { "_Z5floorf", (void *)&floorf, true },
+ { "_Z3fmafff", (void *)&fmaf, true },
+ { "_Z4fmaxff", (void *)&fmaxf, true },
+ { "_Z4fminff", (void *)&fminf, true }, // float fmin(float, float)
+ { "_Z4fmodff", (void *)&fmodf, true },
+ { "_Z5fractfPf", (void *)&SC_fract, true },
+ { "_Z5frexpfPi", (void *)&frexpf, true },
+ { "_Z5hypotff", (void *)&hypotf, true },
+ { "_Z5ilogbf", (void *)&ilogbf, true },
+ { "_Z5ldexpfi", (void *)&ldexpf, true },
+ { "_Z6lgammaf", (void *)&lgammaf, true },
+ { "_Z6lgammafPi", (void *)&lgammaf_r, true },
+ { "_Z3logf", (void *)&logf, true },
+ { "_Z4log2f", (void *)&SC_log2, true },
+ { "_Z5log10f", (void *)&log10f, true },
+ { "_Z5log1pf", (void *)&log1pf, true },
+ { "_Z4logbf", (void *)&logbf, true },
+ { "_Z3madfff", (void *)&SC_mad, true },
+ { "_Z4modffPf", (void *)&modff, true },
+ //{ "_Z3nanj", (void *)&SC_nan, true },
+ { "_Z9nextafterff", (void *)&nextafterf, true },
+ { "_Z3powff", (void *)&powf, true },
+ { "_Z9remainderff", (void *)&remainderf, true },
+ { "_Z6remquoffPi", (void *)&remquof, true },
+ { "_Z4rintf", (void *)&rintf, true },
+ { "_Z5rootnfi", (void *)&SC_rootn, true },
+ { "_Z5roundf", (void *)&roundf, true },
+ { "_Z5rsqrtf", (void *)&SC_rsqrt, true },
+ { "_Z3sinf", (void *)&sinf, true },
+ { "_Z6sincosfPf", (void *)&SC_sincos, true },
+ { "_Z4sinhf", (void *)&sinhf, true },
+ { "_Z4sqrtf", (void *)&sqrtf, true },
+ { "_Z3tanf", (void *)&tanf, true },
+ { "_Z4tanhf", (void *)&tanhf, true },
+ { "_Z6tgammaf", (void *)&tgammaf, true },
+ { "_Z5truncf", (void *)&truncf, true },
+
+ { "_Z3absi", (void *)&SC_abs_i32, true },
+ { "_Z3abss", (void *)&SC_abs_i16, true },
+ { "_Z3absc", (void *)&SC_abs_i8, true },
+ { "_Z3clzj", (void *)&SC_clz_u32, true },
+ { "_Z3clzt", (void *)&SC_clz_u16, true },
+ { "_Z3clzh", (void *)&SC_clz_u8, true },
+ { "_Z3clzi", (void *)&SC_clz_i32, true },
+ { "_Z3clzs", (void *)&SC_clz_i16, true },
+ { "_Z3clzc", (void *)&SC_clz_i8, true },
+ { "_Z3maxjj", (void *)&SC_max_u32, true },
+ { "_Z3maxtt", (void *)&SC_max_u16, true },
+ { "_Z3maxhh", (void *)&SC_max_u8, true },
+ { "_Z3maxii", (void *)&SC_max_i32, true },
+ { "_Z3maxss", (void *)&SC_max_i16, true },
+ { "_Z3maxcc", (void *)&SC_max_i8, true },
+ { "_Z3minjj", (void *)&SC_min_u32, true },
+ { "_Z3mintt", (void *)&SC_min_u16, true },
+ { "_Z3minhh", (void *)&SC_min_u8, true },
+ { "_Z3minii", (void *)&SC_min_i32, true },
+ { "_Z3minss", (void *)&SC_min_i16, true },
+ { "_Z3mincc", (void *)&SC_min_i8, true },
+
+ { "_Z5clampfff", (void *)&SC_clamp_f32, true },
+ { "_Z7degreesf", (void *)&SC_degrees, true },
+ { "_Z3maxff", (void *)&SC_max_f32, true },
+ { "_Z3minff", (void *)&SC_min_f32, true },
+ { "_Z3mixfff", (void *)&SC_mix_f32, true },
+ { "_Z7radiansf", (void *)&SC_radians, true },
+ { "_Z4stepff", (void *)&SC_step_f32, true },
+ //{ "smoothstep", (void *)&, true },
+ { "_Z4signf", (void *)&SC_sign_f32, true },
+
+ // matrix
+ { "_Z20rsMatrixLoadIdentityP12rs_matrix4x4", (void *)&SC_MatrixLoadIdentity_4x4, true },
+ { "_Z20rsMatrixLoadIdentityP12rs_matrix3x3", (void *)&SC_MatrixLoadIdentity_3x3, true },
+ { "_Z20rsMatrixLoadIdentityP12rs_matrix2x2", (void *)&SC_MatrixLoadIdentity_2x2, true },
+
+ { "_Z12rsMatrixLoadP12rs_matrix4x4PKf", (void *)&SC_MatrixLoad_4x4_f, true },
+ { "_Z12rsMatrixLoadP12rs_matrix3x3PKf", (void *)&SC_MatrixLoad_3x3_f, true },
+ { "_Z12rsMatrixLoadP12rs_matrix2x2PKf", (void *)&SC_MatrixLoad_2x2_f, true },
+
+ { "_Z12rsMatrixLoadP12rs_matrix4x4PKS_", (void *)&SC_MatrixLoad_4x4_4x4, true },
+ { "_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix3x3", (void *)&SC_MatrixLoad_4x4_3x3, true },
+ { "_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix2x2", (void *)&SC_MatrixLoad_4x4_2x2, true },
+ { "_Z12rsMatrixLoadP12rs_matrix3x3PKS_", (void *)&SC_MatrixLoad_3x3_3x3, true },
+ { "_Z12rsMatrixLoadP12rs_matrix2x2PKS_", (void *)&SC_MatrixLoad_2x2_2x2, true },
+
+ { "_Z18rsMatrixLoadRotateP12rs_matrix4x4ffff", (void *)&SC_MatrixLoadRotate, true },
+ { "_Z17rsMatrixLoadScaleP12rs_matrix4x4fff", (void *)&SC_MatrixLoadScale, true },
+ { "_Z21rsMatrixLoadTranslateP12rs_matrix4x4fff", (void *)&SC_MatrixLoadTranslate, true },
+ { "_Z14rsMatrixRotateP12rs_matrix4x4ffff", (void *)&SC_MatrixRotate, true },
+ { "_Z13rsMatrixScaleP12rs_matrix4x4fff", (void *)&SC_MatrixScale, true },
+ { "_Z17rsMatrixTranslateP12rs_matrix4x4fff", (void *)&SC_MatrixTranslate, true },
+
+ { "_Z20rsMatrixLoadMultiplyP12rs_matrix4x4PKS_S2_", (void *)&SC_MatrixLoadMultiply_4x4_4x4_4x4, true },
+ { "_Z16rsMatrixMultiplyP12rs_matrix4x4PKS_", (void *)&SC_MatrixMultiply_4x4_4x4, true },
+ { "_Z20rsMatrixLoadMultiplyP12rs_matrix3x3PKS_S2_", (void *)&SC_MatrixLoadMultiply_3x3_3x3_3x3, true },
+ { "_Z16rsMatrixMultiplyP12rs_matrix3x3PKS_", (void *)&SC_MatrixMultiply_3x3_3x3, true },
+ { "_Z20rsMatrixLoadMultiplyP12rs_matrix2x2PKS_S2_", (void *)&SC_MatrixLoadMultiply_2x2_2x2_2x2, true },
+ { "_Z16rsMatrixMultiplyP12rs_matrix2x2PKS_", (void *)&SC_MatrixMultiply_2x2_2x2, true },
+
+ { "_Z17rsMatrixLoadOrthoP12rs_matrix4x4ffffff", (void *)&SC_MatrixLoadOrtho, true },
+ { "_Z19rsMatrixLoadFrustumP12rs_matrix4x4ffffff", (void *)&SC_MatrixLoadFrustum, true },
+ { "_Z23rsMatrixLoadPerspectiveP12rs_matrix4x4ffff", (void *)&SC_MatrixLoadPerspective, true },
+
+ { "_Z15rsMatrixInverseP12rs_matrix4x4", (void *)&SC_MatrixInverse_4x4, true },
+ { "_Z24rsMatrixInverseTransposeP12rs_matrix4x4", (void *)&SC_MatrixInverseTranspose_4x4, true },
+ { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_4x4, true },
+ { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_3x3, true },
+ { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_2x2, true },
+
+ // RS Math
+ { "_Z6rsRandi", (void *)&SC_randi, true },
+ { "_Z6rsRandii", (void *)&SC_randi2, true },
+ { "_Z6rsRandf", (void *)&SC_randf, true },
+ { "_Z6rsRandff", (void *)&SC_randf2, true },
+ { "_Z6rsFracf", (void *)&SC_frac, true },
+
+ { NULL, NULL, false }
+};
+
+const RsdSymbolTable * rsdLookupSymbolMath(const char *sym) {
+ const RsdSymbolTable *syms = gSyms;
+
+ while (syms->mPtr) {
+ if (!strcmp(syms->mName, sym)) {
+ return syms;
+ }
+ syms++;
+ }
+ return NULL;
+}
+
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
new file mode 100644
index 0000000..9cbff95
--- /dev/null
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsScriptC.h"
+#include "rsMatrix4x4.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix2x2.h"
+#include "rsRuntime.h"
+
+#include "utils/Timers.h"
+#include "rsdCore.h"
+
+#include "rsdRuntime.h"
+
+#include <time.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+#define GET_TLS() ScriptTLSStruct * tls = \
+ (ScriptTLSStruct *)pthread_getspecific(rsdgThreadTLSKey); \
+ Context * rsc = tls->mContext; \
+ ScriptC * sc = (ScriptC *) tls->mScript
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Allocation
+//////////////////////////////////////////////////////////////////////////////
+
+static uint32_t SC_allocGetDimX(Allocation *a) {
+ return a->mHal.state.dimensionX;
+}
+
+static uint32_t SC_allocGetDimY(Allocation *a) {
+ return a->mHal.state.dimensionY;
+}
+
+static uint32_t SC_allocGetDimZ(Allocation *a) {
+ return a->mHal.state.dimensionZ;
+}
+
+static uint32_t SC_allocGetDimLOD(Allocation *a) {
+ return a->mHal.state.hasMipmaps;
+}
+
+static uint32_t SC_allocGetDimFaces(Allocation *a) {
+ return a->mHal.state.hasFaces;
+}
+
+static const void * SC_getElementAtX(Allocation *a, uint32_t x) {
+ const uint8_t *p = (const uint8_t *)a->getPtr();
+ return &p[a->mHal.state.elementSizeBytes * x];
+}
+
+static const void * SC_getElementAtXY(Allocation *a, uint32_t x, uint32_t y) {
+ const uint8_t *p = (const uint8_t *)a->getPtr();
+ return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX)];
+}
+
+static const void * SC_getElementAtXYZ(Allocation *a, uint32_t x, uint32_t y, uint32_t z) {
+ const uint8_t *p = (const uint8_t *)a->getPtr();
+ return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX +
+ z * a->mHal.state.dimensionX * a->mHal.state.dimensionY)];
+}
+
+static void SC_AllocationSyncAll2(Allocation *a, RsAllocationUsageType source) {
+ GET_TLS();
+ rsrAllocationSyncAll(rsc, sc, a, source);
+}
+
+static void SC_AllocationSyncAll(Allocation *a) {
+ GET_TLS();
+ rsrAllocationSyncAll(rsc, sc, a, RS_ALLOCATION_USAGE_SCRIPT);
+}
+
+const Allocation * SC_getAllocation(const void *ptr) {
+ GET_TLS();
+ return rsrGetAllocation(rsc, sc, ptr);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Context
+//////////////////////////////////////////////////////////////////////////////
+
+static void SC_BindTexture(ProgramFragment *pf, uint32_t slot, Allocation *a) {
+ GET_TLS();
+ rsrBindTexture(rsc, sc, pf, slot, a);
+}
+
+static void SC_BindSampler(ProgramFragment *pf, uint32_t slot, Sampler *s) {
+ GET_TLS();
+ rsrBindSampler(rsc, sc, pf, slot, s);
+}
+
+static void SC_BindProgramStore(ProgramStore *ps) {
+ GET_TLS();
+ rsrBindProgramStore(rsc, sc, ps);
+}
+
+static void SC_BindProgramFragment(ProgramFragment *pf) {
+ GET_TLS();
+ rsrBindProgramFragment(rsc, sc, pf);
+}
+
+static void SC_BindProgramVertex(ProgramVertex *pv) {
+ GET_TLS();
+ rsrBindProgramVertex(rsc, sc, pv);
+}
+
+static void SC_BindProgramRaster(ProgramRaster *pr) {
+ GET_TLS();
+ rsrBindProgramRaster(rsc, sc, pr);
+}
+
+static void SC_BindFrameBufferObjectColorTarget(Allocation *a, uint32_t slot) {
+ GET_TLS();
+ rsrBindFrameBufferObjectColorTarget(rsc, sc, a, slot);
+}
+
+static void SC_BindFrameBufferObjectDepthTarget(Allocation *a) {
+ GET_TLS();
+ rsrBindFrameBufferObjectDepthTarget(rsc, sc, a);
+}
+
+static void SC_ClearFrameBufferObjectColorTarget(uint32_t slot) {
+ GET_TLS();
+ rsrClearFrameBufferObjectColorTarget(rsc, sc, slot);
+}
+
+static void SC_ClearFrameBufferObjectDepthTarget(Context *, Script *) {
+ GET_TLS();
+ rsrClearFrameBufferObjectDepthTarget(rsc, sc);
+}
+
+static void SC_ClearFrameBufferObjectTargets(Context *, Script *) {
+ GET_TLS();
+ rsrClearFrameBufferObjectTargets(rsc, sc);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// VP
+//////////////////////////////////////////////////////////////////////////////
+
+static void SC_VpLoadProjectionMatrix(const rsc_Matrix *m) {
+ GET_TLS();
+ rsrVpLoadProjectionMatrix(rsc, sc, m);
+}
+
+static void SC_VpLoadModelMatrix(const rsc_Matrix *m) {
+ GET_TLS();
+ rsrVpLoadModelMatrix(rsc, sc, m);
+}
+
+static void SC_VpLoadTextureMatrix(const rsc_Matrix *m) {
+ GET_TLS();
+ rsrVpLoadTextureMatrix(rsc, sc, m);
+}
+
+static void SC_PfConstantColor(ProgramFragment *pf, float r, float g, float b, float a) {
+ GET_TLS();
+ rsrPfConstantColor(rsc, sc, pf, r, g, b, a);
+}
+
+static void SC_VpGetProjectionMatrix(rsc_Matrix *m) {
+ GET_TLS();
+ rsrVpGetProjectionMatrix(rsc, sc, m);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Drawing
+//////////////////////////////////////////////////////////////////////////////
+
+static void SC_DrawQuadTexCoords(float x1, float y1, float z1, float u1, float v1,
+ float x2, float y2, float z2, float u2, float v2,
+ float x3, float y3, float z3, float u3, float v3,
+ float x4, float y4, float z4, float u4, float v4) {
+ GET_TLS();
+ rsrDrawQuadTexCoords(rsc, sc,
+ x1, y1, z1, u1, v1,
+ x2, y2, z2, u2, v2,
+ x3, y3, z3, u3, v3,
+ x4, y4, z4, u4, v4);
+}
+
+static void SC_DrawQuad(float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ float x3, float y3, float z3,
+ float x4, float y4, float z4) {
+ GET_TLS();
+ rsrDrawQuad(rsc, sc, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4);
+}
+
+static void SC_DrawSpriteScreenspace(float x, float y, float z, float w, float h) {
+ GET_TLS();
+ rsrDrawSpriteScreenspace(rsc, sc, x, y, z, w, h);
+}
+
+static void SC_DrawRect(float x1, float y1, float x2, float y2, float z) {
+ GET_TLS();
+ rsrDrawRect(rsc, sc, x1, y1, x2, y2, z);
+}
+
+static void SC_DrawMesh(Mesh *m) {
+ GET_TLS();
+ rsrDrawMesh(rsc, sc, m);
+}
+
+static void SC_DrawMeshPrimitive(Mesh *m, uint32_t primIndex) {
+ GET_TLS();
+ rsrDrawMeshPrimitive(rsc, sc, m, primIndex);
+}
+
+static void SC_DrawMeshPrimitiveRange(Mesh *m, uint32_t primIndex, uint32_t start, uint32_t len) {
+ GET_TLS();
+ rsrDrawMeshPrimitiveRange(rsc, sc, m, primIndex, start, len);
+}
+
+static void SC_MeshComputeBoundingBox(Mesh *m,
+ float *minX, float *minY, float *minZ,
+ float *maxX, float *maxY, float *maxZ) {
+ GET_TLS();
+ rsrMeshComputeBoundingBox(rsc, sc, m, minX, minY, minZ, maxX, maxY, maxZ);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+static void SC_Color(float r, float g, float b, float a) {
+ GET_TLS();
+ rsrColor(rsc, sc, r, g, b, a);
+}
+
+static void SC_Finish() {
+ GET_TLS();
+ rsrFinish(rsc, sc);
+}
+
+static void SC_ClearColor(float r, float g, float b, float a) {
+ GET_TLS();
+ rsrClearColor(rsc, sc, r, g, b, a);
+}
+
+static void SC_ClearDepth(float v) {
+ GET_TLS();
+ rsrClearDepth(rsc, sc, v);
+}
+
+static uint32_t SC_GetWidth() {
+ GET_TLS();
+ return rsrGetWidth(rsc, sc);
+}
+
+static uint32_t SC_GetHeight() {
+ GET_TLS();
+ return rsrGetHeight(rsc, sc);
+}
+
+static void SC_DrawTextAlloc(Allocation *a, int x, int y) {
+ GET_TLS();
+ rsrDrawTextAlloc(rsc, sc, a, x, y);
+}
+
+static void SC_DrawText(const char *text, int x, int y) {
+ GET_TLS();
+ rsrDrawText(rsc, sc, text, x, y);
+}
+
+static void SC_MeasureTextAlloc(Allocation *a,
+ int32_t *left, int32_t *right, int32_t *top, int32_t *bottom) {
+ GET_TLS();
+ rsrMeasureTextAlloc(rsc, sc, a, left, right, top, bottom);
+}
+
+static void SC_MeasureText(const char *text,
+ int32_t *left, int32_t *right, int32_t *top, int32_t *bottom) {
+ GET_TLS();
+ rsrMeasureText(rsc, sc, text, left, right, top, bottom);
+}
+
+static void SC_BindFont(Font *f) {
+ GET_TLS();
+ rsrBindFont(rsc, sc, f);
+}
+
+static void SC_FontColor(float r, float g, float b, float a) {
+ GET_TLS();
+ rsrFontColor(rsc, sc, r, g, b, a);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//////////////////////////////////////////////////////////////////////////////
+
+static void SC_SetObject(ObjectBase **dst, ObjectBase * src) {
+ GET_TLS();
+ rsrSetObject(rsc, sc, dst, src);
+}
+
+static void SC_ClearObject(ObjectBase **dst) {
+ GET_TLS();
+ rsrClearObject(rsc, sc, dst);
+}
+
+static bool SC_IsObject(const ObjectBase *src) {
+ GET_TLS();
+ return rsrIsObject(rsc, sc, src);
+}
+
+
+
+
+static const Allocation * SC_GetAllocation(const void *ptr) {
+ GET_TLS();
+ return rsrGetAllocation(rsc, sc, ptr);
+}
+
+static void SC_ForEach(Script *target,
+ Allocation *in,
+ Allocation *out,
+ const void *usr,
+ const RsScriptCall *call) {
+ GET_TLS();
+ rsrForEach(rsc, sc, target, in, out, usr, 0, NULL);
+}
+
+static void SC_ForEach2(Script *target,
+ Allocation *in,
+ Allocation *out,
+ const void *usr,
+ const RsScriptCall *call) {
+ GET_TLS();
+ rsrForEach(rsc, sc, target, in, out, usr, 0, call);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Time routines
+//////////////////////////////////////////////////////////////////////////////
+
+static float SC_GetDt() {
+ GET_TLS();
+ return rsrGetDt(rsc, sc);
+}
+
+time_t SC_Time(time_t *timer) {
+ GET_TLS();
+ return rsrTime(rsc, sc, timer);
+}
+
+tm* SC_LocalTime(tm *local, time_t *timer) {
+ GET_TLS();
+ return rsrLocalTime(rsc, sc, local, timer);
+}
+
+int64_t SC_UptimeMillis() {
+ GET_TLS();
+ return rsrUptimeMillis(rsc, sc);
+}
+
+int64_t SC_UptimeNanos() {
+ GET_TLS();
+ return rsrUptimeNanos(rsc, sc);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Message routines
+//////////////////////////////////////////////////////////////////////////////
+
+static uint32_t SC_ToClient2(int cmdID, void *data, int len) {
+ GET_TLS();
+ return rsrToClient(rsc, sc, cmdID, data, len);
+}
+
+static uint32_t SC_ToClient(int cmdID) {
+ GET_TLS();
+ return rsrToClient(rsc, sc, cmdID, NULL, 0);
+}
+
+static uint32_t SC_ToClientBlocking2(int cmdID, void *data, int len) {
+ GET_TLS();
+ return rsrToClientBlocking(rsc, sc, cmdID, data, len);
+}
+
+static uint32_t SC_ToClientBlocking(int cmdID) {
+ GET_TLS();
+ return rsrToClientBlocking(rsc, sc, cmdID, NULL, 0);
+}
+
+int SC_divsi3(int a, int b) {
+ return a / b;
+}
+
+int SC_modsi3(int a, int b) {
+ return a % b;
+}
+
+unsigned int SC_udivsi3(unsigned int a, unsigned int b) {
+ return a / b;
+}
+
+unsigned int SC_umodsi3(unsigned int a, unsigned int b) {
+ return a % b;
+}
+
+static void SC_debugF(const char *s, float f) {
+ LOGD("%s %f, 0x%08x", s, f, *((int *) (&f)));
+}
+static void SC_debugFv2(const char *s, float f1, float f2) {
+ LOGD("%s {%f, %f}", s, f1, f2);
+}
+static void SC_debugFv3(const char *s, float f1, float f2, float f3) {
+ LOGD("%s {%f, %f, %f}", s, f1, f2, f3);
+}
+static void SC_debugFv4(const char *s, float f1, float f2, float f3, float f4) {
+ LOGD("%s {%f, %f, %f, %f}", s, f1, f2, f3, f4);
+}
+static void SC_debugD(const char *s, double d) {
+ LOGD("%s %f, 0x%08llx", s, d, *((long long *) (&d)));
+}
+static void SC_debugFM4v4(const char *s, const float *f) {
+ LOGD("%s {%f, %f, %f, %f", s, f[0], f[4], f[8], f[12]);
+ LOGD("%s %f, %f, %f, %f", s, f[1], f[5], f[9], f[13]);
+ LOGD("%s %f, %f, %f, %f", s, f[2], f[6], f[10], f[14]);
+ LOGD("%s %f, %f, %f, %f}", s, f[3], f[7], f[11], f[15]);
+}
+static void SC_debugFM3v3(const char *s, const float *f) {
+ LOGD("%s {%f, %f, %f", s, f[0], f[3], f[6]);
+ LOGD("%s %f, %f, %f", s, f[1], f[4], f[7]);
+ LOGD("%s %f, %f, %f}",s, f[2], f[5], f[8]);
+}
+static void SC_debugFM2v2(const char *s, const float *f) {
+ LOGD("%s {%f, %f", s, f[0], f[2]);
+ LOGD("%s %f, %f}",s, f[1], f[3]);
+}
+
+static void SC_debugI32(const char *s, int32_t i) {
+ LOGD("%s %i 0x%x", s, i, i);
+}
+static void SC_debugU32(const char *s, uint32_t i) {
+ LOGD("%s %u 0x%x", s, i, i);
+}
+static void SC_debugLL64(const char *s, long long ll) {
+ LOGD("%s %lld 0x%llx", s, ll, ll);
+}
+static void SC_debugULL64(const char *s, unsigned long long ll) {
+ LOGD("%s %llu 0x%llx", s, ll, ll);
+}
+
+static void SC_debugP(const char *s, const void *p) {
+ LOGD("%s %p", s, p);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Stub implementation
+//////////////////////////////////////////////////////////////////////////////
+
+// llvm name mangling ref
+// <builtin-type> ::= v # void
+// ::= b # bool
+// ::= c # char
+// ::= a # signed char
+// ::= h # unsigned char
+// ::= s # short
+// ::= t # unsigned short
+// ::= i # int
+// ::= j # unsigned int
+// ::= l # long
+// ::= m # unsigned long
+// ::= x # long long, __int64
+// ::= y # unsigned long long, __int64
+// ::= f # float
+// ::= d # double
+
+static RsdSymbolTable gSyms[] = {
+ { "__divsi3", (void *)&SC_divsi3, true },
+ { "__modsi3", (void *)&SC_modsi3, true },
+ { "__udivsi3", (void *)&SC_udivsi3, true },
+ { "__umodsi3", (void *)&SC_umodsi3, true },
+ { "memset", (void *)&memset, true },
+ { "memcpy", (void *)&memcpy, true },
+
+ // Refcounting
+ { "_Z11rsSetObjectP10rs_elementS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP10rs_element", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject10rs_element", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP7rs_typeS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP7rs_type", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject7rs_type", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP13rs_allocationS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP13rs_allocation", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject13rs_allocation", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP10rs_samplerS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP10rs_sampler", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject10rs_sampler", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP9rs_scriptS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP9rs_script", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject9rs_script", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP7rs_mesh", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject7rs_mesh", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP19rs_program_fragment", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject19rs_program_fragment", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP17rs_program_vertex", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject17rs_program_vertex", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP17rs_program_raster", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject17rs_program_raster", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP16rs_program_store", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject16rs_program_store", (void *)&SC_IsObject, true },
+
+ { "_Z11rsSetObjectP7rs_fontS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP7rs_font", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject7rs_font", (void *)&SC_IsObject, true },
+
+ // Allocation ops
+ { "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX, true },
+ { "_Z19rsAllocationGetDimY13rs_allocation", (void *)&SC_allocGetDimY, true },
+ { "_Z19rsAllocationGetDimZ13rs_allocation", (void *)&SC_allocGetDimZ, true },
+ { "_Z21rsAllocationGetDimLOD13rs_allocation", (void *)&SC_allocGetDimLOD, true },
+ { "_Z23rsAllocationGetDimFaces13rs_allocation", (void *)&SC_allocGetDimFaces, true },
+
+ { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX, true },
+ { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY, true },
+ { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ, true },
+
+ { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation, true },
+
+ { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_AllocationSyncAll, true },
+ { "_Z20rsgAllocationSyncAll13rs_allocation", (void *)&SC_AllocationSyncAll, false },
+ { "_Z20rsgAllocationSyncAll13rs_allocationj", (void *)&SC_AllocationSyncAll2, false },
+ { "_Z15rsGetAllocationPKv", (void *)&SC_GetAllocation, true },
+
+
+ // Messaging
+
+ { "_Z14rsSendToClienti", (void *)&SC_ToClient, false },
+ { "_Z14rsSendToClientiPKvj", (void *)&SC_ToClient2, false },
+ { "_Z22rsSendToClientBlockingi", (void *)&SC_ToClientBlocking, false },
+ { "_Z22rsSendToClientBlockingiPKvj", (void *)&SC_ToClientBlocking2, false },
+
+ { "_Z22rsgBindProgramFragment19rs_program_fragment", (void *)&SC_BindProgramFragment, false },
+ { "_Z19rsgBindProgramStore16rs_program_store", (void *)&SC_BindProgramStore, false },
+ { "_Z20rsgBindProgramVertex17rs_program_vertex", (void *)&SC_BindProgramVertex, false },
+ { "_Z20rsgBindProgramRaster17rs_program_raster", (void *)&SC_BindProgramRaster, false },
+ { "_Z14rsgBindSampler19rs_program_fragmentj10rs_sampler", (void *)&SC_BindSampler, false },
+ { "_Z14rsgBindTexture19rs_program_fragmentj13rs_allocation", (void *)&SC_BindTexture, false },
+
+ { "_Z36rsgProgramVertexLoadProjectionMatrixPK12rs_matrix4x4", (void *)&SC_VpLoadProjectionMatrix, false },
+ { "_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4", (void *)&SC_VpLoadModelMatrix, false },
+ { "_Z33rsgProgramVertexLoadTextureMatrixPK12rs_matrix4x4", (void *)&SC_VpLoadTextureMatrix, false },
+
+ { "_Z35rsgProgramVertexGetProjectionMatrixP12rs_matrix4x4", (void *)&SC_VpGetProjectionMatrix, false },
+
+ { "_Z31rsgProgramFragmentConstantColor19rs_program_fragmentffff", (void *)&SC_PfConstantColor, false },
+
+ { "_Z11rsgGetWidthv", (void *)&SC_GetWidth, false },
+ { "_Z12rsgGetHeightv", (void *)&SC_GetHeight, false },
+
+
+ { "_Z11rsgDrawRectfffff", (void *)&SC_DrawRect, false },
+ { "_Z11rsgDrawQuadffffffffffff", (void *)&SC_DrawQuad, false },
+ { "_Z20rsgDrawQuadTexCoordsffffffffffffffffffff", (void *)&SC_DrawQuadTexCoords, false },
+ { "_Z24rsgDrawSpriteScreenspacefffff", (void *)&SC_DrawSpriteScreenspace, false },
+
+ { "_Z11rsgDrawMesh7rs_mesh", (void *)&SC_DrawMesh, false },
+ { "_Z11rsgDrawMesh7rs_meshj", (void *)&SC_DrawMeshPrimitive, false },
+ { "_Z11rsgDrawMesh7rs_meshjjj", (void *)&SC_DrawMeshPrimitiveRange, false },
+ { "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_", (void *)&SC_MeshComputeBoundingBox, false },
+
+ { "_Z13rsgClearColorffff", (void *)&SC_ClearColor, false },
+ { "_Z13rsgClearDepthf", (void *)&SC_ClearDepth, false },
+
+ { "_Z11rsgDrawTextPKcii", (void *)&SC_DrawText, false },
+ { "_Z11rsgDrawText13rs_allocationii", (void *)&SC_DrawTextAlloc, false },
+ { "_Z14rsgMeasureTextPKcPiS1_S1_S1_", (void *)&SC_MeasureText, false },
+ { "_Z14rsgMeasureText13rs_allocationPiS0_S0_S0_", (void *)&SC_MeasureTextAlloc, false },
+
+ { "_Z11rsgBindFont7rs_font", (void *)&SC_BindFont, false },
+ { "_Z12rsgFontColorffff", (void *)&SC_FontColor, false },
+
+ { "_Z18rsgBindColorTarget13rs_allocationj", (void *)&SC_BindFrameBufferObjectColorTarget, false },
+ { "_Z18rsgBindDepthTarget13rs_allocation", (void *)&SC_BindFrameBufferObjectDepthTarget, false },
+ { "_Z19rsgClearColorTargetj", (void *)&SC_ClearFrameBufferObjectColorTarget, false },
+ { "_Z19rsgClearDepthTargetv", (void *)&SC_ClearFrameBufferObjectDepthTarget, false },
+ { "_Z24rsgClearAllRenderTargetsv", (void *)&SC_ClearFrameBufferObjectTargets, false },
+
+ { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false },
+ { "_Z9rsForEach9rs_script13rs_allocationS0_PKvj", (void *)&SC_ForEach2, false },
+
+ // time
+ { "_Z6rsTimePi", (void *)&SC_Time, true },
+ { "_Z11rsLocaltimeP5rs_tmPKi", (void *)&SC_LocalTime, true },
+ { "_Z14rsUptimeMillisv", (void*)&SC_UptimeMillis, true },
+ { "_Z13rsUptimeNanosv", (void*)&SC_UptimeNanos, true },
+ { "_Z7rsGetDtv", (void*)&SC_GetDt, false },
+
+ // misc
+ { "_Z5colorffff", (void *)&SC_Color, false },
+ { "_Z9rsgFinishv", (void *)&SC_Finish, false },
+
+ // Debug
+ { "_Z7rsDebugPKcf", (void *)&SC_debugF, true },
+ { "_Z7rsDebugPKcff", (void *)&SC_debugFv2, true },
+ { "_Z7rsDebugPKcfff", (void *)&SC_debugFv3, true },
+ { "_Z7rsDebugPKcffff", (void *)&SC_debugFv4, true },
+ { "_Z7rsDebugPKcd", (void *)&SC_debugD, true },
+ { "_Z7rsDebugPKcPK12rs_matrix4x4", (void *)&SC_debugFM4v4, true },
+ { "_Z7rsDebugPKcPK12rs_matrix3x3", (void *)&SC_debugFM3v3, true },
+ { "_Z7rsDebugPKcPK12rs_matrix2x2", (void *)&SC_debugFM2v2, true },
+ { "_Z7rsDebugPKci", (void *)&SC_debugI32, true },
+ { "_Z7rsDebugPKcj", (void *)&SC_debugU32, true },
+ // Both "long" and "unsigned long" need to be redirected to their
+ // 64-bit counterparts, since we have hacked Slang to use 64-bit
+ // for "long" on Arm (to be similar to Java).
+ { "_Z7rsDebugPKcl", (void *)&SC_debugLL64, true },
+ { "_Z7rsDebugPKcm", (void *)&SC_debugULL64, true },
+ { "_Z7rsDebugPKcx", (void *)&SC_debugLL64, true },
+ { "_Z7rsDebugPKcy", (void *)&SC_debugULL64, true },
+ { "_Z7rsDebugPKcPKv", (void *)&SC_debugP, true },
+
+ { NULL, NULL, false }
+};
+
+
+void* rsdLookupRuntimeStub(void* pContext, char const* name) {
+ ScriptC *s = (ScriptC *)pContext;
+ if (!strcmp(name, "__isThreadable")) {
+ return (void*) s->mHal.info.isThreadable;
+ } else if (!strcmp(name, "__clearThreadable")) {
+ s->mHal.info.isThreadable = false;
+ return NULL;
+ }
+
+ RsdSymbolTable *syms = gSyms;
+ const RsdSymbolTable *sym = rsdLookupSymbolMath(name);
+
+ if (!sym) {
+ while (syms->mPtr) {
+ if (!strcmp(syms->mName, name)) {
+ sym = syms;
+ }
+ syms++;
+ }
+ }
+
+ if (sym) {
+ s->mHal.info.isThreadable &= sym->threadable;
+ return sym->mPtr;
+ }
+ LOGE("ScriptC sym lookup failed for %s", name);
+ return NULL;
+}
+
+
diff --git a/libs/rs/driver/rsdSampler.cpp b/libs/rs/driver/rsdSampler.cpp
new file mode 100644
index 0000000..af48c61
--- /dev/null
+++ b/libs/rs/driver/rsdSampler.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdSampler.h"
+
+#include "rsContext.h"
+#include "rsSampler.h"
+#include "rsProgramVertex.h"
+#include "rsProgramFragment.h"
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+
+using namespace android;
+using namespace android::renderscript;
+
+bool rsdSamplerInit(const android::renderscript::Context *,
+ const android::renderscript::Sampler *) {
+ return true;
+}
+
+void rsdSamplerDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::Sampler *s) {
+}
diff --git a/libs/rs/driver/rsdSampler.h b/libs/rs/driver/rsdSampler.h
new file mode 100644
index 0000000..3a64e9e
--- /dev/null
+++ b/libs/rs/driver/rsdSampler.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_SAMPLER_H
+#define RSD_SAMPLER_H
+
+#include <rs_hal.h>
+
+
+bool rsdSamplerInit(const android::renderscript::Context *rsc,
+ const android::renderscript::Sampler *);
+
+void rsdSamplerDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::Sampler *);
+
+
+#endif // RSD_SAMPLER_H
diff --git a/libs/rs/driver/rsdShader.cpp b/libs/rs/driver/rsdShader.cpp
new file mode 100644
index 0000000..15cc417
--- /dev/null
+++ b/libs/rs/driver/rsdShader.cpp
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <rs_hal.h>
+#include <rsContext.h>
+#include <rsProgram.h>
+
+#include "rsdCore.h"
+#include "rsdAllocation.h"
+#include "rsdShader.h"
+#include "rsdShaderCache.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+RsdShader::RsdShader(const Program *p, uint32_t type,
+ const char * shaderText, uint32_t shaderLength) {
+
+ mUserShader.setTo(shaderText, shaderLength);
+ mRSProgram = p;
+ mType = type;
+ initMemberVars();
+ initAttribAndUniformArray();
+ init();
+}
+
+RsdShader::~RsdShader() {
+ if (mShaderID) {
+ glDeleteShader(mShaderID);
+ }
+
+ delete[] mAttribNames;
+ delete[] mUniformNames;
+ delete[] mUniformArraySizes;
+}
+
+void RsdShader::initMemberVars() {
+ mDirty = true;
+ mShaderID = 0;
+ mAttribCount = 0;
+ mUniformCount = 0;
+
+ mAttribNames = NULL;
+ mUniformNames = NULL;
+ mUniformArraySizes = NULL;
+
+ mIsValid = false;
+}
+
+void RsdShader::init() {
+ uint32_t attribCount = 0;
+ uint32_t uniformCount = 0;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
+ initAddUserElement(mRSProgram->mHal.state.inputElements[ct].get(), mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
+ }
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
+ initAddUserElement(mRSProgram->mHal.state.constantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
+ }
+
+ mTextureUniformIndexStart = uniformCount;
+ char buf[256];
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
+ snprintf(buf, sizeof(buf), "UNI_Tex%i", ct);
+ mUniformNames[uniformCount].setTo(buf);
+ mUniformArraySizes[uniformCount] = 1;
+ uniformCount++;
+ }
+}
+
+String8 RsdShader::getGLSLInputString() const {
+ String8 s;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
+ const Element *e = mRSProgram->mHal.state.inputElements[ct].get();
+ for (uint32_t field=0; field < e->getFieldCount(); field++) {
+ const Element *f = e->getField(field);
+
+ // Cannot be complex
+ rsAssert(!f->getFieldCount());
+ switch (f->getComponent().getVectorSize()) {
+ case 1: s.append("attribute float ATTRIB_"); break;
+ case 2: s.append("attribute vec2 ATTRIB_"); break;
+ case 3: s.append("attribute vec3 ATTRIB_"); break;
+ case 4: s.append("attribute vec4 ATTRIB_"); break;
+ default:
+ rsAssert(0);
+ }
+
+ s.append(e->getFieldName(field));
+ s.append(";\n");
+ }
+ }
+ return s;
+}
+
+void RsdShader::appendAttributes() {
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
+ const Element *e = mRSProgram->mHal.state.inputElements[ct].get();
+ for (uint32_t field=0; field < e->getFieldCount(); field++) {
+ const Element *f = e->getField(field);
+ const char *fn = e->getFieldName(field);
+
+ if (fn[0] == '#') {
+ continue;
+ }
+
+ // Cannot be complex
+ rsAssert(!f->getFieldCount());
+ switch (f->getComponent().getVectorSize()) {
+ case 1: mShader.append("attribute float ATTRIB_"); break;
+ case 2: mShader.append("attribute vec2 ATTRIB_"); break;
+ case 3: mShader.append("attribute vec3 ATTRIB_"); break;
+ case 4: mShader.append("attribute vec4 ATTRIB_"); break;
+ default:
+ rsAssert(0);
+ }
+
+ mShader.append(fn);
+ mShader.append(";\n");
+ }
+ }
+}
+
+void RsdShader::appendTextures() {
+ char buf[256];
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
+ if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) {
+ snprintf(buf, sizeof(buf), "uniform sampler2D UNI_Tex%i;\n", ct);
+ } else {
+ snprintf(buf, sizeof(buf), "uniform samplerCube UNI_Tex%i;\n", ct);
+ }
+ mShader.append(buf);
+ }
+}
+
+bool RsdShader::createShader() {
+
+ if (mType == GL_FRAGMENT_SHADER) {
+ mShader.append("precision mediump float;\n");
+ }
+ appendUserConstants();
+ appendAttributes();
+ appendTextures();
+
+ mShader.append(mUserShader);
+
+ return true;
+}
+
+bool RsdShader::loadShader(const Context *rsc) {
+ mShaderID = glCreateShader(mType);
+ rsAssert(mShaderID);
+
+ if (rsc->props.mLogShaders) {
+ LOGV("Loading shader type %x, ID %i", mType, mShaderID);
+ LOGV("%s", mShader.string());
+ }
+
+ if (mShaderID) {
+ const char * ss = mShader.string();
+ glShaderSource(mShaderID, 1, &ss, NULL);
+ glCompileShader(mShaderID);
+
+ GLint compiled = 0;
+ glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLint infoLen = 0;
+ glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen) {
+ char* buf = (char*) malloc(infoLen);
+ if (buf) {
+ glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
+ LOGE("Could not compile shader \n%s\n", buf);
+ free(buf);
+ }
+ glDeleteShader(mShaderID);
+ mShaderID = 0;
+ rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
+ return false;
+ }
+ }
+ }
+
+ if (rsc->props.mLogShaders) {
+ LOGV("--Shader load result %x ", glGetError());
+ }
+ mIsValid = true;
+ return true;
+}
+
+void RsdShader::appendUserConstants() {
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
+ const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
+ for (uint32_t field=0; field < e->getFieldCount(); field++) {
+ const Element *f = e->getField(field);
+ const char *fn = e->getFieldName(field);
+
+ if (fn[0] == '#') {
+ continue;
+ }
+
+ // Cannot be complex
+ rsAssert(!f->getFieldCount());
+ if (f->getType() == RS_TYPE_MATRIX_4X4) {
+ mShader.append("uniform mat4 UNI_");
+ } else if (f->getType() == RS_TYPE_MATRIX_3X3) {
+ mShader.append("uniform mat3 UNI_");
+ } else if (f->getType() == RS_TYPE_MATRIX_2X2) {
+ mShader.append("uniform mat2 UNI_");
+ } else {
+ switch (f->getComponent().getVectorSize()) {
+ case 1: mShader.append("uniform float UNI_"); break;
+ case 2: mShader.append("uniform vec2 UNI_"); break;
+ case 3: mShader.append("uniform vec3 UNI_"); break;
+ case 4: mShader.append("uniform vec4 UNI_"); break;
+ default:
+ rsAssert(0);
+ }
+ }
+
+ mShader.append(fn);
+ if (e->getFieldArraySize(field) > 1) {
+ mShader.appendFormat("[%d]", e->getFieldArraySize(field));
+ }
+ mShader.append(";\n");
+ }
+ }
+}
+
+void RsdShader::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
+ RsDataType dataType = field->getType();
+ uint32_t elementSize = field->getSizeBytes() / sizeof(float);
+ for (uint32_t i = 0; i < arraySize; i ++) {
+ if (arraySize > 1) {
+ LOGV("Array Element [%u]", i);
+ }
+ if (dataType == RS_TYPE_MATRIX_4X4) {
+ LOGV("Matrix4x4");
+ LOGV("{%f, %f, %f, %f", fd[0], fd[4], fd[8], fd[12]);
+ LOGV(" %f, %f, %f, %f", fd[1], fd[5], fd[9], fd[13]);
+ LOGV(" %f, %f, %f, %f", fd[2], fd[6], fd[10], fd[14]);
+ LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
+ } else if (dataType == RS_TYPE_MATRIX_3X3) {
+ LOGV("Matrix3x3");
+ LOGV("{%f, %f, %f", fd[0], fd[3], fd[6]);
+ LOGV(" %f, %f, %f", fd[1], fd[4], fd[7]);
+ LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
+ } else if (dataType == RS_TYPE_MATRIX_2X2) {
+ LOGV("Matrix2x2");
+ LOGV("{%f, %f", fd[0], fd[2]);
+ LOGV(" %f, %f}", fd[1], fd[3]);
+ } else {
+ switch (field->getComponent().getVectorSize()) {
+ case 1:
+ LOGV("Uniform 1 = %f", fd[0]);
+ break;
+ case 2:
+ LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
+ break;
+ case 3:
+ LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
+ break;
+ case 4:
+ LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
+ break;
+ default:
+ rsAssert(0);
+ }
+ }
+ LOGE("Element size %u data=%p", elementSize, fd);
+ fd += elementSize;
+ LOGE("New data=%p", fd);
+ }
+}
+
+void RsdShader::setUniform(const Context *rsc, const Element *field, const float *fd,
+ int32_t slot, uint32_t arraySize ) {
+ RsDataType dataType = field->getType();
+ if (dataType == RS_TYPE_MATRIX_4X4) {
+ glUniformMatrix4fv(slot, arraySize, GL_FALSE, fd);
+ } else if (dataType == RS_TYPE_MATRIX_3X3) {
+ glUniformMatrix3fv(slot, arraySize, GL_FALSE, fd);
+ } else if (dataType == RS_TYPE_MATRIX_2X2) {
+ glUniformMatrix2fv(slot, arraySize, GL_FALSE, fd);
+ } else {
+ switch (field->getComponent().getVectorSize()) {
+ case 1:
+ glUniform1fv(slot, arraySize, fd);
+ break;
+ case 2:
+ glUniform2fv(slot, arraySize, fd);
+ break;
+ case 3:
+ glUniform3fv(slot, arraySize, fd);
+ break;
+ case 4:
+ glUniform4fv(slot, arraySize, fd);
+ break;
+ default:
+ rsAssert(0);
+ }
+ }
+}
+
+void RsdShader::setupSampler(const Context *rsc, const Sampler *s, const Allocation *tex) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ GLenum trans[] = {
+ GL_NEAREST, //RS_SAMPLER_NEAREST,
+ GL_LINEAR, //RS_SAMPLER_LINEAR,
+ GL_LINEAR_MIPMAP_LINEAR, //RS_SAMPLER_LINEAR_MIP_LINEAR,
+ GL_REPEAT, //RS_SAMPLER_WRAP,
+ GL_CLAMP_TO_EDGE, //RS_SAMPLER_CLAMP
+ GL_LINEAR_MIPMAP_NEAREST, //RS_SAMPLER_LINEAR_MIP_NEAREST
+ };
+
+ GLenum transNP[] = {
+ GL_NEAREST, //RS_SAMPLER_NEAREST,
+ GL_LINEAR, //RS_SAMPLER_LINEAR,
+ GL_LINEAR, //RS_SAMPLER_LINEAR_MIP_LINEAR,
+ GL_CLAMP_TO_EDGE, //RS_SAMPLER_WRAP,
+ GL_CLAMP_TO_EDGE, //RS_SAMPLER_CLAMP
+ GL_LINEAR, //RS_SAMPLER_LINEAR_MIP_NEAREST,
+ };
+
+ // This tells us the correct texture type
+ DrvAllocation *drvTex = (DrvAllocation *)tex->mHal.drv;
+ const GLenum target = drvTex->glTarget;
+
+ if (!dc->gl.gl.OES_texture_npot && tex->getType()->getIsNp2()) {
+ if (tex->getHasGraphicsMipmaps() &&
+ (dc->gl.gl.GL_NV_texture_npot_2D_mipmap || dc->gl.gl.GL_IMG_texture_npot)) {
+ if (dc->gl.gl.GL_NV_texture_npot_2D_mipmap) {
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[s->mHal.state.minFilter]);
+ } else {
+ switch (trans[s->mHal.state.minFilter]) {
+ case GL_LINEAR_MIPMAP_LINEAR:
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+ break;
+ default:
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[s->mHal.state.minFilter]);
+ break;
+ }
+ }
+ } else {
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[s->mHal.state.minFilter]);
+ }
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, transNP[s->mHal.state.magFilter]);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, transNP[s->mHal.state.wrapS]);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, transNP[s->mHal.state.wrapT]);
+ } else {
+ if (tex->getHasGraphicsMipmaps()) {
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[s->mHal.state.minFilter]);
+ } else {
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[s->mHal.state.minFilter]);
+ }
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, trans[s->mHal.state.magFilter]);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, trans[s->mHal.state.wrapS]);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, trans[s->mHal.state.wrapT]);
+ }
+
+ float anisoValue = rsMin(dc->gl.gl.EXT_texture_max_aniso, s->mHal.state.aniso);
+ if (dc->gl.gl.EXT_texture_max_aniso > 1.0f) {
+ glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
+ }
+
+ rsdGLCheckError(rsc, "Sampler::setup tex env");
+}
+
+void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) {
+ if (mRSProgram->mHal.state.texturesCount == 0) {
+ return;
+ }
+
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ uint32_t numTexturesToBind = mRSProgram->mHal.state.texturesCount;
+ uint32_t numTexturesAvailable = dc->gl.gl.maxFragmentTextureImageUnits;
+ if (numTexturesToBind >= numTexturesAvailable) {
+ LOGE("Attempting to bind %u textures on shader id %u, but only %u are available",
+ mRSProgram->mHal.state.texturesCount, (uint32_t)this, numTexturesAvailable);
+ rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind more textuers than available");
+ numTexturesToBind = numTexturesAvailable;
+ }
+
+ for (uint32_t ct=0; ct < numTexturesToBind; ct++) {
+ glActiveTexture(GL_TEXTURE0 + ct);
+ if (!mRSProgram->mHal.state.textures[ct].get()) {
+ LOGE("No texture bound for shader id %u, texture unit %u", (uint)this, ct);
+ rsc->setError(RS_ERROR_BAD_SHADER, "No texture bound");
+ continue;
+ }
+
+ DrvAllocation *drvTex = (DrvAllocation *)mRSProgram->mHal.state.textures[ct]->mHal.drv;
+ if (drvTex->glTarget != GL_TEXTURE_2D && drvTex->glTarget != GL_TEXTURE_CUBE_MAP) {
+ LOGE("Attempting to bind unknown texture to shader id %u, texture unit %u", (uint)this, ct);
+ rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
+ }
+ glBindTexture(drvTex->glTarget, drvTex->textureID);
+ rsdGLCheckError(rsc, "ProgramFragment::setup tex bind");
+ if (mRSProgram->mHal.state.samplers[ct].get()) {
+ setupSampler(rsc, mRSProgram->mHal.state.samplers[ct].get(), mRSProgram->mHal.state.textures[ct].get());
+ } else {
+ glTexParameteri(drvTex->glTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(drvTex->glTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(drvTex->glTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(drvTex->glTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ rsdGLCheckError(rsc, "ProgramFragment::setup tex env");
+ }
+
+ glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
+ rsdGLCheckError(rsc, "ProgramFragment::setup uniforms");
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ mDirty = false;
+ rsdGLCheckError(rsc, "ProgramFragment::setup");
+}
+
+void RsdShader::setupUserConstants(const Context *rsc, RsdShaderCache *sc, bool isFragment) {
+ uint32_t uidx = 0;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
+ Allocation *alloc = mRSProgram->mHal.state.constants[ct].get();
+ if (!alloc) {
+ LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set", (uint32_t)this, ct);
+ rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
+ continue;
+ }
+
+ const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
+ const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
+ for (uint32_t field=0; field < e->getFieldCount(); field++) {
+ const Element *f = e->getField(field);
+ const char *fieldName = e->getFieldName(field);
+ // If this field is padding, skip it
+ if (fieldName[0] == '#') {
+ continue;
+ }
+
+ uint32_t offset = e->getFieldOffsetBytes(field);
+ const float *fd = reinterpret_cast<const float *>(&data[offset]);
+
+ int32_t slot = -1;
+ uint32_t arraySize = 1;
+ if (!isFragment) {
+ slot = sc->vtxUniformSlot(uidx);
+ arraySize = sc->vtxUniformSize(uidx);
+ } else {
+ slot = sc->fragUniformSlot(uidx);
+ arraySize = sc->fragUniformSize(uidx);
+ }
+ if (rsc->props.mLogShadersUniforms) {
+ LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
+ }
+ uidx ++;
+ if (slot < 0) {
+ continue;
+ }
+
+ if (rsc->props.mLogShadersUniforms) {
+ logUniform(f, fd, arraySize);
+ }
+ setUniform(rsc, f, fd, slot, arraySize);
+ }
+ }
+}
+
+void RsdShader::setup(const android::renderscript::Context *rsc, RsdShaderCache *sc) {
+
+ setupUserConstants(rsc, sc, mType == GL_FRAGMENT_SHADER);
+ setupTextures(rsc, sc);
+}
+
+void RsdShader::initAttribAndUniformArray() {
+ mAttribCount = 0;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
+ const Element *elem = mRSProgram->mHal.state.inputElements[ct].get();
+ for (uint32_t field=0; field < elem->getFieldCount(); field++) {
+ if (elem->getFieldName(field)[0] != '#') {
+ mAttribCount ++;
+ }
+ }
+ }
+
+ mUniformCount = 0;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
+ const Element *elem = mRSProgram->mHal.state.constantTypes[ct]->getElement();
+
+ for (uint32_t field=0; field < elem->getFieldCount(); field++) {
+ if (elem->getFieldName(field)[0] != '#') {
+ mUniformCount ++;
+ }
+ }
+ }
+ mUniformCount += mRSProgram->mHal.state.texturesCount;
+
+ if (mAttribCount) {
+ mAttribNames = new String8[mAttribCount];
+ }
+ if (mUniformCount) {
+ mUniformNames = new String8[mUniformCount];
+ mUniformArraySizes = new uint32_t[mUniformCount];
+ }
+}
+
+void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix) {
+ rsAssert(e->getFieldCount());
+ for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
+ const Element *ce = e->getField(ct);
+ if (ce->getFieldCount()) {
+ initAddUserElement(ce, names, arrayLengths, count, prefix);
+ } else if (e->getFieldName(ct)[0] != '#') {
+ String8 tmp(prefix);
+ tmp.append(e->getFieldName(ct));
+ names[*count].setTo(tmp.string());
+ if (arrayLengths) {
+ arrayLengths[*count] = e->getFieldArraySize(ct);
+ }
+ (*count)++;
+ }
+ }
+}
diff --git a/libs/rs/driver/rsdShader.h b/libs/rs/driver/rsdShader.h
new file mode 100644
index 0000000..63c4231
--- /dev/null
+++ b/libs/rs/driver/rsdShader.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RSD_SHADER_H
+#define ANDROID_RSD_SHADER_H
+
+#include <utils/String8.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Element;
+class Context;
+class Program;
+
+}
+}
+
+class RsdShaderCache;
+
+#define RS_SHADER_ATTR "ATTRIB_"
+#define RS_SHADER_UNI "UNI_"
+
+class RsdShader {
+public:
+
+ RsdShader(const android::renderscript::Program *p, uint32_t type,
+ const char * shaderText, uint32_t shaderLength);
+ virtual ~RsdShader();
+
+ bool createShader();
+
+ uint32_t getShaderID() const {return mShaderID;}
+
+ uint32_t getAttribCount() const {return mAttribCount;}
+ uint32_t getUniformCount() const {return mUniformCount;}
+ const android::String8 & getAttribName(uint32_t i) const {return mAttribNames[i];}
+ const android::String8 & getUniformName(uint32_t i) const {return mUniformNames[i];}
+ uint32_t getUniformArraySize(uint32_t i) const {return mUniformArraySizes[i];}
+
+ android::String8 getGLSLInputString() const;
+
+ bool isValid() const {return mIsValid;}
+ void forceDirty() const {mDirty = true;}
+
+ bool loadShader(const android::renderscript::Context *);
+ void setup(const android::renderscript::Context *, RsdShaderCache *sc);
+
+protected:
+
+ const android::renderscript::Program *mRSProgram;
+ bool mIsValid;
+
+ // Applies to vertex and fragment shaders only
+ void appendUserConstants();
+ void setupUserConstants(const android::renderscript::Context *rsc, RsdShaderCache *sc, bool isFragment);
+ void initAddUserElement(const android::renderscript::Element *e, android::String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix);
+ void setupTextures(const android::renderscript::Context *rsc, RsdShaderCache *sc);
+ void setupSampler(const android::renderscript::Context *rsc, const android::renderscript::Sampler *s, const android::renderscript::Allocation *tex);
+
+ void appendAttributes();
+ void appendTextures();
+
+ void initAttribAndUniformArray();
+
+ mutable bool mDirty;
+ android::String8 mShader;
+ android::String8 mUserShader;
+ uint32_t mShaderID;
+ uint32_t mType;
+
+ uint32_t mTextureCount;
+ uint32_t mAttribCount;
+ uint32_t mUniformCount;
+ android::String8 *mAttribNames;
+ android::String8 *mUniformNames;
+ uint32_t *mUniformArraySizes;
+
+ int32_t mTextureUniformIndexStart;
+
+ void logUniform(const android::renderscript::Element *field, const float *fd, uint32_t arraySize );
+ void setUniform(const android::renderscript::Context *rsc, const android::renderscript::Element *field, const float *fd, int32_t slot, uint32_t arraySize );
+ void initMemberVars();
+ void init();
+};
+
+#endif //ANDROID_RSD_SHADER_H
+
+
+
+
diff --git a/libs/rs/driver/rsdShaderCache.cpp b/libs/rs/driver/rsdShaderCache.cpp
new file mode 100644
index 0000000..d11490c
--- /dev/null
+++ b/libs/rs/driver/rsdShaderCache.cpp
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <rs_hal.h>
+#include <rsContext.h>
+
+#include "rsdShader.h"
+#include "rsdShaderCache.h"
+#include "rsdGL.h"
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+
+RsdShaderCache::RsdShaderCache() {
+ mEntries.setCapacity(16);
+ mVertexDirty = true;
+ mFragmentDirty = true;
+}
+
+RsdShaderCache::~RsdShaderCache() {
+ cleanupAll();
+}
+
+void RsdShaderCache::updateUniformArrayData(const Context *rsc, RsdShader *prog, uint32_t linkedID,
+ UniformData *data, const char* logTag,
+ UniformQueryData **uniformList, uint32_t uniListSize) {
+
+ for (uint32_t ct=0; ct < prog->getUniformCount(); ct++) {
+ if (data[ct].slot >= 0 && data[ct].arraySize > 1) {
+ //Iterate over the list of active GL uniforms and find highest array index
+ for (uint32_t ui = 0; ui < uniListSize; ui ++) {
+ if (prog->getUniformName(ct) == uniformList[ui]->name) {
+ data[ct].arraySize = (uint32_t)uniformList[ui]->arraySize;
+ break;
+ }
+ }
+ }
+
+ if (rsc->props.mLogShaders) {
+ LOGV("%s U, %s = %d, arraySize = %d\n", logTag,
+ prog->getUniformName(ct).string(), data[ct].slot, data[ct].arraySize);
+ }
+ }
+}
+
+void RsdShaderCache::populateUniformData(RsdShader *prog, uint32_t linkedID, UniformData *data) {
+ for (uint32_t ct=0; ct < prog->getUniformCount(); ct++) {
+ data[ct].slot = glGetUniformLocation(linkedID, prog->getUniformName(ct));
+ data[ct].arraySize = prog->getUniformArraySize(ct);
+ }
+}
+
+bool RsdShaderCache::hasArrayUniforms(RsdShader *vtx, RsdShader *frag) {
+ UniformData *data = mCurrent->vtxUniforms;
+ for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) {
+ if (data[ct].slot >= 0 && data[ct].arraySize > 1) {
+ return true;
+ }
+ }
+ data = mCurrent->fragUniforms;
+ for (uint32_t ct=0; ct < frag->getUniformCount(); ct++) {
+ if (data[ct].slot >= 0 && data[ct].arraySize > 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool RsdShaderCache::setup(const Context *rsc) {
+ if (!mVertexDirty && !mFragmentDirty) {
+ return true;
+ }
+
+ if (!link(rsc)) {
+ return false;
+ }
+
+ if (mFragmentDirty) {
+ mFragment->setup(rsc, this);
+ mFragmentDirty = false;
+ }
+ if (mVertexDirty) {
+ mVertex->setup(rsc, this);
+ mVertexDirty = false;
+ }
+
+ return true;
+}
+
+bool RsdShaderCache::link(const Context *rsc) {
+
+ RsdShader *vtx = mVertex;
+ RsdShader *frag = mFragment;
+ if (!vtx->getShaderID()) {
+ vtx->loadShader(rsc);
+ }
+ if (!frag->getShaderID()) {
+ frag->loadShader(rsc);
+ }
+
+ // Don't try to cache if shaders failed to load
+ if (!vtx->getShaderID() || !frag->getShaderID()) {
+ return false;
+ }
+ //LOGV("rsdShaderCache lookup vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID());
+ uint32_t entryCount = mEntries.size();
+ for (uint32_t ct = 0; ct < entryCount; ct ++) {
+ if ((mEntries[ct]->vtx == vtx->getShaderID()) &&
+ (mEntries[ct]->frag == frag->getShaderID())) {
+
+ //LOGV("SC using program %i", mEntries[ct]->program);
+ glUseProgram(mEntries[ct]->program);
+ mCurrent = mEntries[ct];
+ //LOGV("RsdShaderCache hit, using %i", ct);
+ rsdGLCheckError(rsc, "RsdShaderCache::link (hit)");
+ return true;
+ }
+ }
+
+ //LOGV("RsdShaderCache miss");
+ //LOGE("e0 %x", glGetError());
+ ProgramEntry *e = new ProgramEntry(vtx->getAttribCount(),
+ vtx->getUniformCount(),
+ frag->getUniformCount());
+ mEntries.push(e);
+ mCurrent = e;
+ e->vtx = vtx->getShaderID();
+ e->frag = frag->getShaderID();
+ e->program = glCreateProgram();
+ if (e->program) {
+ GLuint pgm = e->program;
+ glAttachShader(pgm, vtx->getShaderID());
+ //LOGE("e1 %x", glGetError());
+ glAttachShader(pgm, frag->getShaderID());
+
+ glBindAttribLocation(pgm, 0, "ATTRIB_position");
+ glBindAttribLocation(pgm, 1, "ATTRIB_color");
+ glBindAttribLocation(pgm, 2, "ATTRIB_normal");
+ glBindAttribLocation(pgm, 3, "ATTRIB_texture0");
+
+ //LOGE("e2 %x", glGetError());
+ glLinkProgram(pgm);
+ //LOGE("e3 %x", glGetError());
+ GLint linkStatus = GL_FALSE;
+ glGetProgramiv(pgm, GL_LINK_STATUS, &linkStatus);
+ if (linkStatus != GL_TRUE) {
+ GLint bufLength = 0;
+ glGetProgramiv(pgm, GL_INFO_LOG_LENGTH, &bufLength);
+ if (bufLength) {
+ char* buf = (char*) malloc(bufLength);
+ if (buf) {
+ glGetProgramInfoLog(pgm, bufLength, NULL, buf);
+ LOGE("Could not link program:\n%s\n", buf);
+ free(buf);
+ }
+ }
+ glDeleteProgram(pgm);
+ rsc->setError(RS_ERROR_FATAL_PROGRAM_LINK, "Error linking GL Programs");
+ return false;
+ }
+
+ for (uint32_t ct=0; ct < e->vtxAttrCount; ct++) {
+ e->vtxAttrs[ct].slot = glGetAttribLocation(pgm, vtx->getAttribName(ct));
+ e->vtxAttrs[ct].name = vtx->getAttribName(ct).string();
+ if (rsc->props.mLogShaders) {
+ LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->vtxAttrs[ct].slot);
+ }
+ }
+
+ populateUniformData(vtx, pgm, e->vtxUniforms);
+ populateUniformData(frag, pgm, e->fragUniforms);
+
+ // Only populate this list if we have arrays in our uniforms
+ UniformQueryData **uniformList = NULL;
+ GLint numUniforms = 0;
+ bool hasArrays = hasArrayUniforms(vtx, frag);
+ if (hasArrays) {
+ // Get the number of active uniforms and the length of the longest name
+ glGetProgramiv(pgm, GL_ACTIVE_UNIFORMS, &numUniforms);
+ GLint maxNameLength = 0;
+ glGetProgramiv(pgm, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
+ if (numUniforms > 0 && maxNameLength > 0) {
+ uniformList = new UniformQueryData*[numUniforms];
+ // Iterate over all the uniforms and build the list we
+ // can later use to match our uniforms to
+ for (uint32_t ct = 0; ct < (uint32_t)numUniforms; ct++) {
+ uniformList[ct] = new UniformQueryData(maxNameLength);
+ glGetActiveUniform(pgm, ct, maxNameLength, &uniformList[ct]->writtenLength,
+ &uniformList[ct]->arraySize, &uniformList[ct]->type,
+ uniformList[ct]->name);
+ //LOGE("GL UNI idx=%u, arraySize=%u, name=%s", ct,
+ // uniformList[ct]->arraySize, uniformList[ct]->name);
+ }
+ }
+ }
+
+ // We now know the highest index of all of the array uniforms
+ // and we need to update our cache to reflect that
+ // we may have declared [n], but only m < n elements are used
+ updateUniformArrayData(rsc, vtx, pgm, e->vtxUniforms, "vtx",
+ uniformList, (uint32_t)numUniforms);
+ updateUniformArrayData(rsc, frag, pgm, e->fragUniforms, "frag",
+ uniformList, (uint32_t)numUniforms);
+
+ // Clean up the uniform data from GL
+ if (uniformList != NULL) {
+ for (uint32_t ct = 0; ct < (uint32_t)numUniforms; ct++) {
+ delete uniformList[ct];
+ }
+ delete[] uniformList;
+ uniformList = NULL;
+ }
+ }
+
+ //LOGV("SC made program %i", e->program);
+ glUseProgram(e->program);
+ rsdGLCheckError(rsc, "RsdShaderCache::link (miss)");
+
+ return true;
+}
+
+int32_t RsdShaderCache::vtxAttribSlot(const String8 &attrName) const {
+ for (uint32_t ct=0; ct < mCurrent->vtxAttrCount; ct++) {
+ if (attrName == mCurrent->vtxAttrs[ct].name) {
+ return mCurrent->vtxAttrs[ct].slot;
+ }
+ }
+ return -1;
+}
+
+void RsdShaderCache::cleanupVertex(uint32_t id) {
+ int32_t numEntries = (int32_t)mEntries.size();
+ for (int32_t ct = 0; ct < numEntries; ct ++) {
+ if (mEntries[ct]->vtx == id) {
+ glDeleteProgram(mEntries[ct]->program);
+
+ delete mEntries[ct];
+ mEntries.removeAt(ct);
+ numEntries = (int32_t)mEntries.size();
+ ct --;
+ }
+ }
+}
+
+void RsdShaderCache::cleanupFragment(uint32_t id) {
+ int32_t numEntries = (int32_t)mEntries.size();
+ for (int32_t ct = 0; ct < numEntries; ct ++) {
+ if (mEntries[ct]->frag == id) {
+ glDeleteProgram(mEntries[ct]->program);
+
+ delete mEntries[ct];
+ mEntries.removeAt(ct);
+ numEntries = (int32_t)mEntries.size();
+ ct --;
+ }
+ }
+}
+
+void RsdShaderCache::cleanupAll() {
+ for (uint32_t ct=0; ct < mEntries.size(); ct++) {
+ glDeleteProgram(mEntries[ct]->program);
+ free(mEntries[ct]);
+ }
+ mEntries.clear();
+}
+
diff --git a/libs/rs/driver/rsdShaderCache.h b/libs/rs/driver/rsdShaderCache.h
new file mode 100644
index 0000000..17ee3e8
--- /dev/null
+++ b/libs/rs/driver/rsdShaderCache.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RSD_SHADER_CACHE_H
+#define ANDROID_RSD_SHADER_CACHE_H
+
+namespace android {
+namespace renderscript {
+
+class Context;
+
+}
+}
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+class RsdShader;
+
+// ---------------------------------------------------------------------------
+
+// An element is a group of Components that occupies one cell in a structure.
+class RsdShaderCache {
+public:
+ RsdShaderCache();
+ virtual ~RsdShaderCache();
+
+ void setActiveVertex(RsdShader *pv) {
+ mVertexDirty = true;
+ mVertex = pv;
+ }
+
+ void setActiveFragment(RsdShader *pf) {
+ mFragmentDirty = true;
+ mFragment = pf;
+ }
+
+ bool setup(const android::renderscript::Context *rsc);
+
+ void cleanupVertex(uint32_t id);
+ void cleanupFragment(uint32_t id);
+
+ void cleanupAll();
+
+ int32_t vtxAttribSlot(const android::String8 &attrName) const;
+ int32_t vtxUniformSlot(uint32_t a) const {return mCurrent->vtxUniforms[a].slot;}
+ uint32_t vtxUniformSize(uint32_t a) const {return mCurrent->vtxUniforms[a].arraySize;}
+ int32_t fragUniformSlot(uint32_t a) const {return mCurrent->fragUniforms[a].slot;}
+ uint32_t fragUniformSize(uint32_t a) const {return mCurrent->fragUniforms[a].arraySize;}
+
+protected:
+ bool link(const android::renderscript::Context *rsc);
+ bool mFragmentDirty;
+ bool mVertexDirty;
+ RsdShader *mVertex;
+ RsdShader *mFragment;
+
+ struct UniformQueryData {
+ char *name;
+ uint32_t nameLength;
+ int32_t writtenLength;
+ int32_t arraySize;
+ uint32_t type;
+ UniformQueryData(uint32_t maxName) {
+ name = NULL;
+ nameLength = maxName;
+ if (nameLength > 0 ) {
+ name = new char[nameLength];
+ }
+ }
+ ~UniformQueryData() {
+ if (name != NULL) {
+ delete[] name;
+ name = NULL;
+ }
+ }
+ };
+ struct UniformData {
+ int32_t slot;
+ uint32_t arraySize;
+ };
+ struct AttrData {
+ int32_t slot;
+ const char* name;
+ };
+ struct ProgramEntry {
+ ProgramEntry(uint32_t numVtxAttr, uint32_t numVtxUnis,
+ uint32_t numFragUnis) : vtx(0), frag(0), program(0), vtxAttrCount(0),
+ vtxAttrs(0), vtxUniforms(0), fragUniforms(0) {
+ vtxAttrCount = numVtxAttr;
+ if (numVtxAttr) {
+ vtxAttrs = new AttrData[numVtxAttr];
+ }
+ if (numVtxUnis) {
+ vtxUniforms = new UniformData[numVtxUnis];
+ }
+ if (numFragUnis) {
+ fragUniforms = new UniformData[numFragUnis];
+ }
+ }
+ ~ProgramEntry() {
+ if (vtxAttrs) {
+ delete[] vtxAttrs;
+ vtxAttrs = NULL;
+ }
+ if (vtxUniforms) {
+ delete[] vtxUniforms;
+ vtxUniforms = NULL;
+ }
+ if (fragUniforms) {
+ delete[] fragUniforms;
+ fragUniforms = NULL;
+ }
+ }
+ uint32_t vtx;
+ uint32_t frag;
+ uint32_t program;
+ uint32_t vtxAttrCount;
+ AttrData *vtxAttrs;
+ UniformData *vtxUniforms;
+ UniformData *fragUniforms;
+ };
+ android::Vector<ProgramEntry*> mEntries;
+ ProgramEntry *mCurrent;
+
+ bool hasArrayUniforms(RsdShader *vtx, RsdShader *frag);
+ void populateUniformData(RsdShader *prog, uint32_t linkedID, UniformData *data);
+ void updateUniformArrayData(const android::renderscript::Context *rsc,
+ RsdShader *prog, uint32_t linkedID,
+ UniformData *data, const char* logTag,
+ UniformQueryData **uniformList, uint32_t uniListSize);
+};
+
+
+#endif //ANDROID_RSD_SHADER_CACHE_H
+
+
+
+
diff --git a/libs/rs/driver/rsdVertexArray.cpp b/libs/rs/driver/rsdVertexArray.cpp
new file mode 100644
index 0000000..62ec107
--- /dev/null
+++ b/libs/rs/driver/rsdVertexArray.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <rs_hal.h>
+#include <rsContext.h>
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+
+#include "rsdGL.h"
+#include "rsdCore.h"
+#include "rsdVertexArray.h"
+#include "rsdShaderCache.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+RsdVertexArray::RsdVertexArray(const Attrib *attribs, uint32_t numAttribs) {
+ mAttribs = attribs;
+ mCount = numAttribs;
+}
+
+RsdVertexArray::~RsdVertexArray() {
+}
+
+RsdVertexArray::Attrib::Attrib() {
+ clear();
+}
+
+void RsdVertexArray::Attrib::clear() {
+ buffer = 0;
+ offset = 0;
+ type = 0;
+ size = 0;
+ stride = 0;
+ ptr = NULL;
+ normalized = false;
+ name.setTo("");
+}
+
+void RsdVertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride,
+ bool normalized, uint32_t offset,
+ const char *name) {
+ clear();
+ this->type = type;
+ this->size = size;
+ this->offset = offset;
+ this->normalized = normalized;
+ this->stride = stride;
+ this->name.setTo(name);
+}
+
+void RsdVertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
+ if (idx == 0) {
+ LOGV("Starting vertex attribute binding");
+ }
+ LOGV("va %i: slot=%i name=%s buf=%i ptr=%p size=%i type=0x%x stride=0x%x norm=%i offset=0x%x",
+ idx, slot,
+ mAttribs[idx].name.string(),
+ mAttribs[idx].buffer,
+ mAttribs[idx].ptr,
+ mAttribs[idx].size,
+ mAttribs[idx].type,
+ mAttribs[idx].stride,
+ mAttribs[idx].normalized,
+ mAttribs[idx].offset);
+}
+
+void RsdVertexArray::setup(const Context *rsc) const {
+
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ RsdVertexArrayState *state = dc->gl.vertexArrayState;
+ RsdShaderCache *sc = dc->gl.shaderCache;
+
+ rsdGLCheckError(rsc, "RsdVertexArray::setup start");
+ uint32_t maxAttrs = state->mAttrsEnabledSize;
+
+ for (uint32_t ct=1; ct < maxAttrs; ct++) {
+ if(state->mAttrsEnabled[ct]) {
+ glDisableVertexAttribArray(ct);
+ state->mAttrsEnabled[ct] = false;
+ }
+ }
+
+ rsdGLCheckError(rsc, "RsdVertexArray::setup disabled");
+ for (uint32_t ct=0; ct < mCount; ct++) {
+ int32_t slot = sc->vtxAttribSlot(mAttribs[ct].name);
+ if (rsc->props.mLogShadersAttr) {
+ logAttrib(ct, slot);
+ }
+ if (slot < 0 || slot >= (int32_t)maxAttrs) {
+ continue;
+ }
+ glEnableVertexAttribArray(slot);
+ state->mAttrsEnabled[slot] = true;
+ glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+ glVertexAttribPointer(slot,
+ mAttribs[ct].size,
+ mAttribs[ct].type,
+ mAttribs[ct].normalized,
+ mAttribs[ct].stride,
+ mAttribs[ct].ptr + mAttribs[ct].offset);
+ }
+ rsdGLCheckError(rsc, "RsdVertexArray::setup done");
+}
+////////////////////////////////////////////
+RsdVertexArrayState::RsdVertexArrayState() {
+ mAttrsEnabled = NULL;
+ mAttrsEnabledSize = 0;
+}
+
+RsdVertexArrayState::~RsdVertexArrayState() {
+ if (mAttrsEnabled) {
+ delete[] mAttrsEnabled;
+ mAttrsEnabled = NULL;
+ }
+}
+void RsdVertexArrayState::init(uint32_t maxAttrs) {
+ mAttrsEnabledSize = maxAttrs;
+ mAttrsEnabled = new bool[mAttrsEnabledSize];
+ for (uint32_t ct = 0; ct < mAttrsEnabledSize; ct++) {
+ mAttrsEnabled[ct] = false;
+ }
+}
+
diff --git a/libs/rs/driver/rsdVertexArray.h b/libs/rs/driver/rsdVertexArray.h
new file mode 100644
index 0000000..3e807a3
--- /dev/null
+++ b/libs/rs/driver/rsdVertexArray.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RSD_VERTEX_ARRAY_H
+#define ANDROID_RSD_VERTEX_ARRAY_H
+
+namespace android {
+namespace renderscript {
+
+class Context;
+
+}
+}
+
+#include <utils/String8.h>
+
+// An element is a group of Components that occupies one cell in a structure.
+class RsdVertexArray {
+public:
+ class Attrib {
+ public:
+ uint32_t buffer;
+ const uint8_t * ptr;
+ uint32_t offset;
+ uint32_t type;
+ uint32_t size;
+ uint32_t stride;
+ bool normalized;
+ android::String8 name;
+
+ Attrib();
+ void clear();
+ void set(uint32_t type, uint32_t size, uint32_t stride, bool normalized, uint32_t offset, const char *name);
+ };
+
+ RsdVertexArray(const Attrib *attribs, uint32_t numAttribs);
+ virtual ~RsdVertexArray();
+
+ void setup(const android::renderscript::Context *rsc) const;
+ void logAttrib(uint32_t idx, uint32_t slot) const;
+
+protected:
+ void clear(uint32_t index);
+ uint32_t mActiveBuffer;
+ const uint8_t * mActivePointer;
+ uint32_t mCount;
+
+ const Attrib *mAttribs;
+};
+
+
+class RsdVertexArrayState {
+public:
+ RsdVertexArrayState();
+ ~RsdVertexArrayState();
+ void init(uint32_t maxAttrs);
+
+ bool *mAttrsEnabled;
+ uint32_t mAttrsEnabledSize;
+};
+
+
+#endif //ANDROID_RSD_VERTEX_ARRAY_H
+
+
+