summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/binder/IPCThreadState.cpp3
-rw-r--r--libs/binder/Parcel.cpp24
-rw-r--r--libs/camera/Android.mk1
-rw-r--r--libs/camera/Camera.cpp16
-rw-r--r--libs/camera/CameraParameters.cpp10
-rw-r--r--libs/camera/ICamera.cpp36
-rw-r--r--libs/gui/Android.mk15
-rw-r--r--libs/gui/IGraphicBufferAlloc.cpp (renamed from libs/surfaceflinger_client/IGraphicBufferAlloc.cpp)39
-rw-r--r--libs/gui/ISurface.cpp (renamed from libs/surfaceflinger_client/ISurface.cpp)0
-rw-r--r--libs/gui/ISurfaceComposer.cpp (renamed from libs/surfaceflinger_client/ISurfaceComposer.cpp)0
-rw-r--r--libs/gui/ISurfaceComposerClient.cpp (renamed from libs/surfaceflinger_client/ISurfaceComposerClient.cpp)5
-rw-r--r--libs/gui/ISurfaceTexture.cpp73
-rw-r--r--libs/gui/LayerState.cpp (renamed from libs/surfaceflinger_client/LayerState.cpp)0
-rw-r--r--libs/gui/Sensor.cpp8
-rw-r--r--libs/gui/SharedBufferStack.cpp (renamed from libs/surfaceflinger_client/SharedBufferStack.cpp)0
-rw-r--r--libs/gui/Surface.cpp (renamed from libs/surfaceflinger_client/Surface.cpp)45
-rw-r--r--libs/gui/SurfaceComposerClient.cpp (renamed from libs/surfaceflinger_client/SurfaceComposerClient.cpp)6
-rw-r--r--libs/gui/SurfaceTexture.cpp635
-rw-r--r--libs/gui/SurfaceTextureClient.cpp151
-rw-r--r--libs/gui/tests/Android.mk5
-rw-r--r--libs/gui/tests/SurfaceTextureClient_test.cpp420
-rw-r--r--libs/gui/tests/SurfaceTexture_test.cpp8
-rw-r--r--libs/gui/tests/Surface_test.cpp (renamed from libs/surfaceflinger_client/tests/Surface_test.cpp)4
-rw-r--r--libs/hwui/Android.mk2
-rw-r--r--libs/hwui/Caches.cpp49
-rw-r--r--libs/hwui/Caches.h6
-rw-r--r--libs/hwui/Debug.h6
-rw-r--r--libs/hwui/DisplayListLogBuffer.cpp124
-rw-r--r--libs/hwui/DisplayListLogBuffer.h52
-rw-r--r--libs/hwui/DisplayListRenderer.cpp382
-rw-r--r--libs/hwui/DisplayListRenderer.h24
-rw-r--r--libs/hwui/FontRenderer.cpp82
-rw-r--r--libs/hwui/FontRenderer.h63
-rw-r--r--libs/hwui/Layer.h46
-rw-r--r--libs/hwui/LayerCache.cpp2
-rw-r--r--libs/hwui/LayerRenderer.cpp52
-rw-r--r--libs/hwui/LayerRenderer.h3
-rw-r--r--libs/hwui/Matrix.cpp4
-rw-r--r--libs/hwui/Matrix.h1
-rw-r--r--libs/hwui/OpenGLRenderer.cpp707
-rw-r--r--libs/hwui/OpenGLRenderer.h30
-rw-r--r--libs/hwui/Patch.cpp32
-rw-r--r--libs/hwui/Patch.h6
-rw-r--r--libs/hwui/PathCache.h4
-rw-r--r--libs/hwui/Program.cpp9
-rw-r--r--libs/hwui/Program.h2
-rw-r--r--libs/hwui/ProgramCache.cpp130
-rw-r--r--libs/hwui/ProgramCache.h29
-rw-r--r--libs/hwui/Properties.h5
-rw-r--r--libs/hwui/ShapeCache.h16
-rw-r--r--libs/hwui/TextDropShadowCache.h1
-rw-r--r--libs/hwui/Vertex.h47
-rw-r--r--libs/hwui/utils/GenerationCache.h245
-rw-r--r--libs/rs/Android.mk89
-rw-r--r--libs/rs/RenderScript.h331
-rw-r--r--libs/rs/RenderScriptDefines.h341
-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.cpp (renamed from libs/rs/rsScriptC_LibCL.cpp)192
-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.cpp (renamed from libs/rs/rsShaderCache.cpp)79
-rw-r--r--libs/rs/driver/rsdShaderCache.h (renamed from libs/rs/rsShaderCache.h)61
-rw-r--r--libs/rs/driver/rsdVertexArray.cpp (renamed from libs/rs/rsVertexArray.cpp)49
-rw-r--r--libs/rs/driver/rsdVertexArray.h (renamed from libs/rs/rsVertexArray.h)39
-rw-r--r--libs/rs/rs.spec225
-rw-r--r--libs/rs/rsAllocation.cpp524
-rw-r--r--libs/rs/rsAllocation.h117
-rw-r--r--libs/rs/rsComponent.cpp38
-rw-r--r--libs/rs/rsComponent.h2
-rw-r--r--libs/rs/rsContext.cpp767
-rw-r--r--libs/rs/rsContext.h144
-rw-r--r--libs/rs/rsElement.cpp11
-rw-r--r--libs/rs/rsFBOCache.cpp96
-rw-r--r--libs/rs/rsFBOCache.h66
-rw-r--r--libs/rs/rsFifo.cpp31
-rw-r--r--libs/rs/rsFifo.h49
-rw-r--r--libs/rs/rsFifoSocket.cpp83
-rw-r--r--libs/rs/rsFifoSocket.h54
-rw-r--r--libs/rs/rsFont.cpp91
-rw-r--r--libs/rs/rsFont.h8
-rw-r--r--libs/rs/rsHandcode.h96
-rw-r--r--libs/rs/rsMatrix.cpp155
-rw-r--r--libs/rs/rsMatrix2x2.cpp63
-rw-r--r--libs/rs/rsMatrix2x2.h62
-rw-r--r--libs/rs/rsMatrix3x3.cpp76
-rw-r--r--libs/rs/rsMatrix3x3.h62
-rw-r--r--libs/rs/rsMatrix4x4.cpp314
-rw-r--r--libs/rs/rsMatrix4x4.h (renamed from libs/rs/rsMatrix.h)41
-rw-r--r--libs/rs/rsMesh.cpp336
-rw-r--r--libs/rs/rsMesh.h63
-rw-r--r--libs/rs/rsProgram.cpp432
-rw-r--r--libs/rs/rsProgram.h95
-rw-r--r--libs/rs/rsProgramBase.h44
-rw-r--r--libs/rs/rsProgramFragment.cpp115
-rw-r--r--libs/rs/rsProgramFragment.h5
-rw-r--r--libs/rs/rsProgramRaster.cpp73
-rw-r--r--libs/rs/rsProgramRaster.h32
-rw-r--r--libs/rs/rsProgramStore.cpp236
-rw-r--r--libs/rs/rsProgramStore.h60
-rw-r--r--libs/rs/rsProgramVertex.cpp121
-rw-r--r--libs/rs/rsProgramVertex.h6
-rw-r--r--libs/rs/rsRuntime.h203
-rw-r--r--libs/rs/rsSampler.cpp150
-rw-r--r--libs/rs/rsSampler.h32
-rw-r--r--libs/rs/rsScript.cpp65
-rw-r--r--libs/rs/rsScript.h35
-rw-r--r--libs/rs/rsScriptC.cpp500
-rw-r--r--libs/rs/rsScriptC.h26
-rw-r--r--libs/rs/rsScriptC_Lib.cpp931
-rw-r--r--libs/rs/rsScriptC_LibGL.cpp375
-rw-r--r--libs/rs/rsThreadIO.cpp162
-rw-r--r--libs/rs/rsThreadIO.h44
-rw-r--r--libs/rs/rsType.cpp9
-rw-r--r--libs/rs/rsType.h3
-rw-r--r--libs/rs/rsUtils.h4
-rw-r--r--libs/rs/rs_hal.h176
-rw-r--r--libs/rs/rsg_generator.c426
-rw-r--r--libs/rs/scriptc/rs_graphics.rsh40
-rw-r--r--libs/rs/scriptc/rs_types.rsh11
-rw-r--r--libs/rs/spec.h3
-rw-r--r--libs/rs/spec.l34
-rw-r--r--libs/surfaceflinger_client/Android.mk17
-rw-r--r--libs/surfaceflinger_client/tests/Android.mk53
-rw-r--r--libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk17
-rw-r--r--libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp284
-rw-r--r--libs/ui/FramebufferNativeWindow.cpp20
-rw-r--r--libs/ui/GraphicBuffer.cpp8
-rw-r--r--libs/ui/Input.cpp47
-rw-r--r--libs/ui/InputTransport.cpp16
-rw-r--r--libs/ui/tests/InputEvent_test.cpp25
-rw-r--r--libs/ui/tests/InputPublisherAndConsumer_test.cpp72
-rw-r--r--libs/utils/AssetManager.cpp2
-rw-r--r--libs/utils/BackupData.cpp16
-rw-r--r--libs/utils/BackupHelpers.cpp272
158 files changed, 11766 insertions, 6370 deletions
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 95cfddf..392193b 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -851,6 +851,9 @@ status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
+ tr.cookie = 0;
+ tr.sender_pid = 0;
+ tr.sender_euid = 0;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index d57f2c9..a0fc4d0 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -338,7 +338,7 @@ void Parcel::setDataPosition(size_t pos) const
status_t Parcel::setDataCapacity(size_t size)
{
- if (size > mDataSize) return continueWrite(size);
+ if (size > mDataCapacity) return continueWrite(size);
return NO_ERROR;
}
@@ -353,12 +353,12 @@ status_t Parcel::setData(const uint8_t* buffer, size_t len)
return err;
}
-status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len)
+status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
{
const sp<ProcessState> proc(ProcessState::self());
status_t err;
- uint8_t *data = parcel->mData;
- size_t *objects = parcel->mObjects;
+ const uint8_t *data = parcel->mData;
+ const size_t *objects = parcel->mObjects;
size_t size = parcel->mObjectsSize;
int startPos = mDataPos;
int firstIndex = -1, lastIndex = -2;
@@ -386,10 +386,12 @@ status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len)
}
int numObjects = lastIndex - firstIndex + 1;
- // grow data
- err = growData(len);
- if (err != NO_ERROR) {
- return err;
+ if ((mDataSize+len) > mDataCapacity) {
+ // grow data
+ err = growData(len);
+ if (err != NO_ERROR) {
+ return err;
+ }
}
// append data
@@ -1384,8 +1386,10 @@ status_t Parcel::continueWrite(size_t desired)
return NO_MEMORY;
}
} else {
- mDataSize = desired;
- LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize);
+ if (mDataSize > desired) {
+ mDataSize = desired;
+ LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize);
+ }
if (mDataPos > desired) {
mDataPos = desired;
LOGV("continueWrite Setting data pos of %p to %d\n", this, mDataPos);
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index 2f16923..b17b3d2 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -13,7 +13,6 @@ LOCAL_SHARED_LIBRARIES := \
libutils \
libbinder \
libhardware \
- libsurfaceflinger_client \
libui \
libgui
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index e288312..5eb48da 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -205,22 +205,6 @@ status_t Camera::startPreview()
return c->startPreview();
}
-int32_t Camera::getNumberOfVideoBuffers() const
-{
- LOGV("getNumberOfVideoBuffers");
- sp <ICamera> c = mCamera;
- if (c == 0) return 0;
- return c->getNumberOfVideoBuffers();
-}
-
-sp<IMemory> Camera::getVideoBuffer(int32_t index) const
-{
- LOGV("getVideoBuffer: %d", index);
- sp <ICamera> c = mCamera;
- if (c == 0) return 0;
- return c->getVideoBuffer(index);
-}
-
status_t Camera::storeMetaDataInBuffers(bool enabled)
{
LOGV("storeMetaDataInBuffers: %s",
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 0fd79a4..9392cf2 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -59,6 +59,8 @@ const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode";
const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values";
const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode";
const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values";
+const char CameraParameters::KEY_MAX_NUM_FOCUS_AREAS[] = "max-num-focus-areas";
+const char CameraParameters::KEY_FOCUS_AREAS[] = "focus-areas";
const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length";
const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle";
const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle";
@@ -66,6 +68,12 @@ const char CameraParameters::KEY_EXPOSURE_COMPENSATION[] = "exposure-compensatio
const char CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION[] = "max-exposure-compensation";
const char CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION[] = "min-exposure-compensation";
const char CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP[] = "exposure-compensation-step";
+const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK[] = "auto-exposure-lock";
+const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED[] = "auto-exposure-lock-supported";
+const char CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK[] = "auto-whitebalance-lock";
+const char CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED[] = "auto-whitebalance-lock-supported";
+const char CameraParameters::KEY_MAX_NUM_METERING_AREAS[] = "max-num-metering-areas";
+const char CameraParameters::KEY_METERING_AREAS[] = "metering-areas";
const char CameraParameters::KEY_ZOOM[] = "zoom";
const char CameraParameters::KEY_MAX_ZOOM[] = "max-zoom";
const char CameraParameters::KEY_ZOOM_RATIOS[] = "zoom-ratios";
@@ -78,6 +86,7 @@ const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
const char CameraParameters::TRUE[] = "true";
+const char CameraParameters::FALSE[] = "false";
const char CameraParameters::FOCUS_DISTANCE_INFINITY[] = "Infinity";
// Values for white balance settings.
@@ -137,6 +146,7 @@ const char CameraParameters::PIXEL_FORMAT_YUV420SP[] = "yuv420sp";
const char CameraParameters::PIXEL_FORMAT_YUV422I[] = "yuv422i-yuyv";
const char CameraParameters::PIXEL_FORMAT_YUV420P[] = "yuv420p";
const char CameraParameters::PIXEL_FORMAT_RGB565[] = "rgb565";
+const char CameraParameters::PIXEL_FORMAT_RGBA8888[] = "rgba8888";
const char CameraParameters::PIXEL_FORMAT_JPEG[] = "jpeg";
// Values for focus mode settings.
diff --git a/libs/camera/ICamera.cpp b/libs/camera/ICamera.cpp
index 931b57d..5f6e5ef 100644
--- a/libs/camera/ICamera.cpp
+++ b/libs/camera/ICamera.cpp
@@ -46,8 +46,6 @@ enum {
STOP_RECORDING,
RECORDING_ENABLED,
RELEASE_RECORDING_FRAME,
- GET_NUM_VIDEO_BUFFERS,
- GET_VIDEO_BUFFER,
STORE_META_DATA_IN_BUFFERS,
};
@@ -149,27 +147,6 @@ public:
remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
}
- int32_t getNumberOfVideoBuffers() const
- {
- LOGV("getNumberOfVideoBuffers");
- Parcel data, reply;
- data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
- remote()->transact(GET_NUM_VIDEO_BUFFERS, data, &reply);
- return reply.readInt32();
- }
-
- sp<IMemory> getVideoBuffer(int32_t index) const
- {
- LOGV("getVideoBuffer: %d", index);
- Parcel data, reply;
- data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
- data.writeInt32(index);
- remote()->transact(GET_VIDEO_BUFFER, data, &reply);
- sp<IMemory> mem = interface_cast<IMemory>(
- reply.readStrongBinder());
- return mem;
- }
-
status_t storeMetaDataInBuffers(bool enabled)
{
LOGV("storeMetaDataInBuffers: %s", enabled? "true": "false");
@@ -355,19 +332,6 @@ status_t BnCamera::onTransact(
releaseRecordingFrame(mem);
return NO_ERROR;
} break;
- case GET_NUM_VIDEO_BUFFERS: {
- LOGV("GET_NUM_VIDEO_BUFFERS");
- CHECK_INTERFACE(ICamera, data, reply);
- reply->writeInt32(getNumberOfVideoBuffers());
- return NO_ERROR;
- } break;
- case GET_VIDEO_BUFFER: {
- LOGV("GET_VIDEO_BUFFER");
- CHECK_INTERFACE(ICamera, data, reply);
- int32_t index = data.readInt32();
- reply->writeStrongBinder(getVideoBuffer(index)->asBinder());
- return NO_ERROR;
- } break;
case STORE_META_DATA_IN_BUFFERS: {
LOGV("STORE_META_DATA_IN_BUFFERS");
CHECK_INTERFACE(ICamera, data, reply);
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index d1a6af1..b5737ff 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -10,7 +10,15 @@ LOCAL_SRC_FILES:= \
SensorEventQueue.cpp \
SensorManager.cpp \
SurfaceTexture.cpp \
- SurfaceTextureClient.cpp
+ SurfaceTextureClient.cpp \
+ ISurfaceComposer.cpp \
+ ISurface.cpp \
+ ISurfaceComposerClient.cpp \
+ IGraphicBufferAlloc.cpp \
+ LayerState.cpp \
+ SharedBufferStack.cpp \
+ Surface.cpp \
+ SurfaceComposerClient.cpp \
LOCAL_SHARED_LIBRARIES := \
libcutils \
@@ -21,7 +29,6 @@ LOCAL_SHARED_LIBRARIES := \
libui \
libEGL \
libGLESv2 \
- libsurfaceflinger_client
LOCAL_MODULE:= libgui
@@ -31,3 +38,7 @@ ifeq ($(TARGET_SIMULATOR),true)
endif
include $(BUILD_SHARED_LIBRARY)
+
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index e05da72..0cd51da 100644
--- a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -32,7 +32,6 @@ namespace android {
enum {
CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- FREE_ALL_GRAPHIC_BUFFERS_EXCEPT,
};
class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
@@ -46,8 +45,7 @@ public:
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
PixelFormat format, uint32_t usage) {
Parcel data, reply;
- data.writeInterfaceToken(
- IGraphicBufferAlloc::getInterfaceDescriptor());
+ data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
data.writeInt32(w);
data.writeInt32(h);
data.writeInt32(format);
@@ -58,17 +56,12 @@ public:
if (nonNull) {
graphicBuffer = new GraphicBuffer();
reply.read(*graphicBuffer);
+ // reply.readStrongBinder();
+ // here we don't even have to read the BufferReference from
+ // the parcel, it'll die with the parcel.
}
return graphicBuffer;
}
-
- virtual void freeAllGraphicBuffersExcept(int bufIdx) {
- Parcel data, reply;
- data.writeInterfaceToken(
- IGraphicBufferAlloc::getInterfaceDescriptor());
- data.writeInt32(bufIdx);
- remote()->transact(FREE_ALL_GRAPHIC_BUFFERS_EXCEPT, data, &reply);
- }
};
IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
@@ -80,6 +73,17 @@ status_t BnGraphicBufferAlloc::onTransact(
{
// codes that don't require permission check
+ /* BufferReference just keeps a strong reference to a
+ * GraphicBuffer until it is destroyed (that is, until
+ * no local or remote process have a reference to it).
+ */
+ class BufferReference : public BBinder {
+ sp<GraphicBuffer> buffer;
+ public:
+ BufferReference(const sp<GraphicBuffer>& buffer) : buffer(buffer) { }
+ };
+
+
switch(code) {
case CREATE_GRAPHIC_BUFFER: {
CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
@@ -91,15 +95,16 @@ status_t BnGraphicBufferAlloc::onTransact(
reply->writeInt32(result != 0);
if (result != 0) {
reply->write(*result);
+ // We add a BufferReference to this parcel to make sure the
+ // buffer stays alive until the GraphicBuffer object on
+ // the other side has been created.
+ // This is needed so that the buffer handle can be
+ // registered before the buffer is destroyed on implementations
+ // that do not use file-descriptors to track their buffers.
+ reply->writeStrongBinder( new BufferReference(result) );
}
return NO_ERROR;
} break;
- case FREE_ALL_GRAPHIC_BUFFERS_EXCEPT: {
- CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
- int bufIdx = data.readInt32();
- freeAllGraphicBuffersExcept(bufIdx);
- return NO_ERROR;
- } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/surfaceflinger_client/ISurface.cpp b/libs/gui/ISurface.cpp
index 23b90af..23b90af 100644
--- a/libs/surfaceflinger_client/ISurface.cpp
+++ b/libs/gui/ISurface.cpp
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 8951c3f..8951c3f 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
diff --git a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 7730eb1..ea38e08 100644
--- a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -83,7 +83,6 @@ public:
}
virtual sp<ISurface> createSurface( surface_data_t* params,
- int pid,
const String8& name,
DisplayID display,
uint32_t w,
@@ -93,7 +92,6 @@ public:
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
- data.writeInt32(pid);
data.writeString8(name);
data.writeInt32(display);
data.writeInt32(w);
@@ -172,14 +170,13 @@ status_t BnSurfaceComposerClient::onTransact(
case CREATE_SURFACE: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
surface_data_t params;
- int32_t pid = data.readInt32();
String8 name = data.readString8();
DisplayID display = data.readInt32();
uint32_t w = data.readInt32();
uint32_t h = data.readInt32();
PixelFormat format = data.readInt32();
uint32_t flags = data.readInt32();
- sp<ISurface> s = createSurface(&params, pid, name, display, w, h,
+ sp<ISurface> s = createSurface(&params, name, display, w, h,
format, flags);
params.writeToParcel(reply);
reply->writeStrongBinder(s->asBinder());
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index d661fd5..16e3780 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -39,6 +39,8 @@ enum {
SET_CROP,
SET_TRANSFORM,
GET_ALLOCATOR,
+ QUERY,
+ SET_SYNCHRONOUS_MODE,
};
@@ -50,15 +52,10 @@ public:
{
}
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+ virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(bufferIdx);
- data.writeInt32(w);
- data.writeInt32(h);
- data.writeInt32(format);
- data.writeInt32(usage);
remote()->transact(REQUEST_BUFFER, data, &reply);
sp<GraphicBuffer> buffer;
bool nonNull = reply.readInt32();
@@ -79,19 +76,25 @@ public:
return err;
}
- virtual status_t dequeueBuffer(int *buf) {
+ virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+ uint32_t format, uint32_t usage) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+ data.writeInt32(w);
+ data.writeInt32(h);
+ data.writeInt32(format);
+ data.writeInt32(usage);
remote()->transact(DEQUEUE_BUFFER, data, &reply);
*buf = reply.readInt32();
int result = reply.readInt32();
return result;
}
- virtual status_t queueBuffer(int buf) {
+ virtual status_t queueBuffer(int buf, int64_t timestamp) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(buf);
+ data.writeInt64(timestamp);
remote()->transact(QUEUE_BUFFER, data, &reply);
status_t result = reply.readInt32();
return result;
@@ -131,6 +134,27 @@ public:
remote()->transact(GET_ALLOCATOR, data, &reply);
return reply.readStrongBinder();
}
+
+ virtual int query(int what, int* value) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+ data.writeInt32(what);
+ remote()->transact(QUERY, data, &reply);
+ value[0] = reply.readInt32();
+ status_t result = reply.readInt32();
+ return result;
+ }
+
+ virtual status_t setSynchronousMode(bool enabled) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+ data.writeInt32(enabled);
+ remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
+ status_t result = reply.readInt32();
+ return result;
+ }
+
+
};
IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
@@ -144,12 +168,7 @@ status_t BnSurfaceTexture::onTransact(
case REQUEST_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int bufferIdx = data.readInt32();
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- uint32_t format = data.readInt32();
- uint32_t usage = data.readInt32();
- sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format,
- usage));
+ sp<GraphicBuffer> buffer(requestBuffer(bufferIdx));
reply->writeInt32(buffer != 0);
if (buffer != 0) {
reply->write(*buffer);
@@ -165,8 +184,12 @@ status_t BnSurfaceTexture::onTransact(
} break;
case DEQUEUE_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
+ uint32_t w = data.readInt32();
+ uint32_t h = data.readInt32();
+ uint32_t format = data.readInt32();
+ uint32_t usage = data.readInt32();
int buf;
- int result = dequeueBuffer(&buf);
+ int result = dequeueBuffer(&buf, w, h, format, usage);
reply->writeInt32(buf);
reply->writeInt32(result);
return NO_ERROR;
@@ -174,7 +197,8 @@ status_t BnSurfaceTexture::onTransact(
case QUEUE_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int buf = data.readInt32();
- status_t result = queueBuffer(buf);
+ int64_t timestamp = data.readInt64();
+ status_t result = queueBuffer(buf, timestamp);
reply->writeInt32(result);
return NO_ERROR;
} break;
@@ -196,7 +220,6 @@ status_t BnSurfaceTexture::onTransact(
return NO_ERROR;
} break;
case SET_TRANSFORM: {
- Rect reg;
CHECK_INTERFACE(ISurfaceTexture, data, reply);
uint32_t transform = data.readInt32();
status_t result = setTransform(transform);
@@ -209,6 +232,22 @@ status_t BnSurfaceTexture::onTransact(
reply->writeStrongBinder(result);
return NO_ERROR;
} break;
+ case QUERY: {
+ CHECK_INTERFACE(ISurfaceTexture, data, reply);
+ int value;
+ int what = data.readInt32();
+ int res = query(what, &value);
+ reply->writeInt32(value);
+ reply->writeInt32(res);
+ return NO_ERROR;
+ } break;
+ case SET_SYNCHRONOUS_MODE: {
+ CHECK_INTERFACE(ISurfaceTexture, data, reply);
+ bool enabled = data.readInt32();
+ status_t res = setSynchronousMode(enabled);
+ reply->writeInt32(res);
+ return NO_ERROR;
+ } break;
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/surfaceflinger_client/LayerState.cpp b/libs/gui/LayerState.cpp
index 01c4c7e..01c4c7e 100644
--- a/libs/surfaceflinger_client/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index b1f37ff..f9a2c04 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -89,6 +89,14 @@ int32_t Sensor::getMinDelay() const {
return mMinDelay;
}
+nsecs_t Sensor::getMinDelayNs() const {
+ return getMinDelay() * 1000;
+}
+
+int32_t Sensor::getVersion() const {
+ return mVersion;
+}
+
size_t Sensor::getFlattenedSize() const
{
return sizeof(int32_t) + ((mName.length() + 3) & ~3) +
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/gui/SharedBufferStack.cpp
index 7505d53..7505d53 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/gui/SharedBufferStack.cpp
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/gui/Surface.cpp
index 21d509a..0c5767b 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -502,8 +502,8 @@ status_t Surface::validate(bool inCancelBuffer) const
return NO_ERROR;
}
-sp<ISurface> Surface::getISurface() const {
- return mSurface;
+sp<IBinder> Surface::asBinder() const {
+ return mSurface!=0 ? mSurface->asBinder() : 0;
}
// ----------------------------------------------------------------------------
@@ -513,32 +513,32 @@ int Surface::setSwapInterval(ANativeWindow* window, int interval) {
}
int Surface::dequeueBuffer(ANativeWindow* window,
- android_native_buffer_t** buffer) {
+ ANativeWindowBuffer** buffer) {
Surface* self = getSelf(window);
return self->dequeueBuffer(buffer);
}
int Surface::cancelBuffer(ANativeWindow* window,
- android_native_buffer_t* buffer) {
+ ANativeWindowBuffer* buffer) {
Surface* self = getSelf(window);
return self->cancelBuffer(buffer);
}
int Surface::lockBuffer(ANativeWindow* window,
- android_native_buffer_t* buffer) {
+ ANativeWindowBuffer* buffer) {
Surface* self = getSelf(window);
return self->lockBuffer(buffer);
}
int Surface::queueBuffer(ANativeWindow* window,
- android_native_buffer_t* buffer) {
+ ANativeWindowBuffer* buffer) {
Surface* self = getSelf(window);
return self->queueBuffer(buffer);
}
-int Surface::query(ANativeWindow* window,
+int Surface::query(const ANativeWindow* window,
int what, int* value) {
- Surface* self = getSelf(window);
+ const Surface* self = getSelf(window);
return self->query(what, value);
}
@@ -570,7 +570,7 @@ bool Surface::needNewBuffer(int bufIdx,
return newNeewBuffer;
}
-int Surface::dequeueBuffer(android_native_buffer_t** buffer)
+int Surface::dequeueBuffer(ANativeWindowBuffer** buffer)
{
status_t err = validate();
if (err != NO_ERROR)
@@ -624,7 +624,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
return err;
}
-int Surface::cancelBuffer(android_native_buffer_t* buffer)
+int Surface::cancelBuffer(ANativeWindowBuffer* buffer)
{
status_t err = validate(true);
switch (err) {
@@ -651,7 +651,7 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer)
}
-int Surface::lockBuffer(android_native_buffer_t* buffer)
+int Surface::lockBuffer(ANativeWindowBuffer* buffer)
{
status_t err = validate();
if (err != NO_ERROR)
@@ -670,7 +670,7 @@ int Surface::lockBuffer(android_native_buffer_t* buffer)
return err;
}
-int Surface::queueBuffer(android_native_buffer_t* buffer)
+int Surface::queueBuffer(ANativeWindowBuffer* buffer)
{
status_t err = validate();
if (err != NO_ERROR)
@@ -697,7 +697,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
return err;
}
-int Surface::query(int what, int* value)
+int Surface::query(int what, int* value) const
{
switch (what) {
case NATIVE_WINDOW_WIDTH:
@@ -753,6 +753,9 @@ int Surface::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
res = dispatch_set_buffers_transform( args );
break;
+ case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+ res = dispatch_set_buffers_timestamp( args );
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -792,6 +795,11 @@ int Surface::dispatch_set_buffers_transform(va_list args) {
return setBuffersTransform(transform);
}
+int Surface::dispatch_set_buffers_timestamp(va_list args) {
+ int64_t timestamp = va_arg(args, int64_t);
+ return setBuffersTimestamp(timestamp);
+}
+
void Surface::setUsage(uint32_t reqUsage)
{
Mutex::Autolock _l(mSurfaceLock);
@@ -910,6 +918,13 @@ int Surface::setBuffersTransform(int transform)
return NO_ERROR;
}
+int Surface::setBuffersTimestamp(int64_t timestamp)
+{
+ // Surface doesn't really have anything meaningful to do with timestamps
+ // so they'll just be dropped here.
+ return NO_ERROR;
+}
+
// ----------------------------------------------------------------------------
int Surface::getConnectedApi() const
@@ -954,7 +969,7 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
// we're intending to do software rendering from this point
setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
- android_native_buffer_t* out;
+ ANativeWindowBuffer* out;
status_t err = dequeueBuffer(&out);
LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
if (err == NO_ERROR) {
@@ -1048,7 +1063,7 @@ int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const
if (idx < 0) {
// The buffer doesn't have an index set. See if the handle the same as
// one of the buffers for which we do know the index. This can happen
- // e.g. if GraphicBuffer is used to wrap an android_native_buffer_t that
+ // e.g. if GraphicBuffer is used to wrap an ANativeWindowBuffer that
// was dequeued from an ANativeWindow.
for (size_t i = 0; i < mBuffers.size(); i++) {
if (mBuffers[i] != 0 && buffer->handle == mBuffers[i]->handle) {
diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index d336724..a1ff2c1 100644
--- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -273,7 +273,6 @@ ssize_t SurfaceComposerClient::getNumberOfDisplays()
}
sp<SurfaceControl> SurfaceComposerClient::createSurface(
- int pid,
DisplayID display,
uint32_t w,
uint32_t h,
@@ -286,12 +285,11 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(
snprintf(buffer, SIZE, "<pid_%d>", getpid());
name.append(buffer);
- return SurfaceComposerClient::createSurface(pid, name, display,
+ return SurfaceComposerClient::createSurface(name, display,
w, h, format, flags);
}
sp<SurfaceControl> SurfaceComposerClient::createSurface(
- int pid,
const String8& name,
DisplayID display,
uint32_t w,
@@ -302,7 +300,7 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(
sp<SurfaceControl> result;
if (mStatus == NO_ERROR) {
ISurfaceComposerClient::surface_data_t data;
- sp<ISurface> surface = mClient->createSurface(&data, pid, name,
+ sp<ISurface> surface = mClient->createSurface(&data, name,
display, w, h, format, flags);
if (surface != 0) {
result = new SurfaceControl(this, surface, data, w, h, format, flags);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 5c6d71b..ee97dcf 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -27,11 +27,14 @@
#include <gui/SurfaceTexture.h>
+#include <hardware/hardware.h>
+
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <surfaceflinger/IGraphicBufferAlloc.h>
#include <utils/Log.h>
+#include <utils/String8.h>
namespace android {
@@ -76,17 +79,23 @@ static float mtxRot270[16] = {
static void mtxMul(float out[16], const float a[16], const float b[16]);
SurfaceTexture::SurfaceTexture(GLuint tex) :
- mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
- mCurrentTransform(0), mLastQueued(INVALID_BUFFER_SLOT),
- mLastQueuedTransform(0), mNextTransform(0), mTexName(tex) {
+ mDefaultWidth(1),
+ mDefaultHeight(1),
+ mPixelFormat(PIXEL_FORMAT_RGBA_8888),
+ mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+ mClientBufferCount(0),
+ mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+ mCurrentTexture(INVALID_BUFFER_SLOT),
+ mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
+ mCurrentTransform(0),
+ mCurrentTimestamp(0),
+ mNextTransform(0),
+ mTexName(tex),
+ mSynchronousMode(false) {
LOGV("SurfaceTexture::SurfaceTexture");
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
- mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
- mSlots[i].mOwnedByClient = false;
- }
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
+ mNextCrop.makeInvalid();
}
SurfaceTexture::~SurfaceTexture() {
@@ -94,23 +103,94 @@ SurfaceTexture::~SurfaceTexture() {
freeAllBuffers();
}
+status_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) {
+ if (bufferCount > NUM_BUFFER_SLOTS)
+ return BAD_VALUE;
+
+ // special-case, nothing to do
+ if (bufferCount == mBufferCount)
+ return OK;
+
+ if (!mClientBufferCount &&
+ bufferCount >= mBufferCount) {
+ // easy, we just have more buffers
+ mBufferCount = bufferCount;
+ mServerBufferCount = bufferCount;
+ mDequeueCondition.signal();
+ } else {
+ // we're here because we're either
+ // - reducing the number of available buffers
+ // - or there is a client-buffer-count in effect
+
+ // less than 2 buffers is never allowed
+ if (bufferCount < 2)
+ return BAD_VALUE;
+
+ // when there is non client-buffer-count in effect, the client is not
+ // allowed to dequeue more than one buffer at a time,
+ // so the next time they dequeue a buffer, we know that they don't
+ // own one. the actual resizing will happen during the next
+ // dequeueBuffer.
+
+ mServerBufferCount = bufferCount;
+ }
+ return OK;
+}
+
+status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
+ Mutex::Autolock lock(mMutex);
+ return setBufferCountServerLocked(bufferCount);
+}
+
status_t SurfaceTexture::setBufferCount(int bufferCount) {
LOGV("SurfaceTexture::setBufferCount");
+ Mutex::Autolock lock(mMutex);
+
+ // Error out if the user has dequeued buffers
+ for (int i=0 ; i<mBufferCount ; i++) {
+ if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
+ LOGE("setBufferCount: client owns some buffers");
+ return -EINVAL;
+ }
+ }
+
+ if (bufferCount == 0) {
+ const int minBufferSlots = mSynchronousMode ?
+ MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+ mClientBufferCount = 0;
+ bufferCount = (mServerBufferCount >= minBufferSlots) ?
+ mServerBufferCount : minBufferSlots;
+ return setBufferCountServerLocked(bufferCount);
+ }
- if (bufferCount < MIN_BUFFER_SLOTS) {
+ // We don't allow the client to set a buffer-count less than
+ // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it.
+ if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) {
return BAD_VALUE;
}
- Mutex::Autolock lock(mMutex);
+ // here we're guaranteed that the client doesn't have dequeued buffers
+ // and will release all of its buffer references.
freeAllBuffers();
mBufferCount = bufferCount;
+ mClientBufferCount = bufferCount;
mCurrentTexture = INVALID_BUFFER_SLOT;
- mLastQueued = INVALID_BUFFER_SLOT;
+ mQueue.clear();
+ mDequeueCondition.signal();
return OK;
}
-sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
+{
+ Mutex::Autolock lock(mMutex);
+ if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
+ mDefaultWidth = w;
+ mDefaultHeight = h;
+ }
+ return OK;
+}
+
+sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) {
LOGV("SurfaceTexture::requestBuffer");
Mutex::Autolock lock(mMutex);
if (buf < 0 || mBufferCount <= buf) {
@@ -118,62 +198,250 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
mBufferCount, buf);
return 0;
}
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- sp<GraphicBuffer> graphicBuffer(
- mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
- if (graphicBuffer == 0) {
- LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
- } else {
+ mSlots[buf].mRequestBufferCalled = true;
+ return mSlots[buf].mGraphicBuffer;
+}
+
+status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
+ uint32_t format, uint32_t usage) {
+ LOGV("SurfaceTexture::dequeueBuffer");
+
+ if ((w && !h) || (!w & h)) {
+ LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMutex);
+
+ status_t returnFlags(OK);
+
+ int found, foundSync;
+ int dequeuedCount = 0;
+ bool tryAgain = true;
+ while (tryAgain) {
+ // We need to wait for the FIFO to drain if the number of buffer
+ // needs to change.
+ //
+ // The condition "number of buffer needs to change" is true if
+ // - the client doesn't care about how many buffers there are
+ // - AND the actual number of buffer is different from what was
+ // set in the last setBufferCountServer()
+ // - OR -
+ // setBufferCountServer() was set to a value incompatible with
+ // the synchronization mode (for instance because the sync mode
+ // changed since)
+ //
+ // As long as this condition is true AND the FIFO is not empty, we
+ // wait on mDequeueCondition.
+
+ int minBufferCountNeeded = mSynchronousMode ?
+ MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+
+ if (!mClientBufferCount &&
+ ((mServerBufferCount != mBufferCount) ||
+ (mServerBufferCount < minBufferCountNeeded))) {
+ // wait for the FIFO to drain
+ while (!mQueue.isEmpty()) {
+ mDequeueCondition.wait(mMutex);
+ }
+ minBufferCountNeeded = mSynchronousMode ?
+ MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+ }
+
+
+ if (!mClientBufferCount &&
+ ((mServerBufferCount != mBufferCount) ||
+ (mServerBufferCount < minBufferCountNeeded))) {
+ // here we're guaranteed that mQueue is empty
+ freeAllBuffers();
+ mBufferCount = mServerBufferCount;
+ if (mBufferCount < minBufferCountNeeded)
+ mBufferCount = minBufferCountNeeded;
+ mCurrentTexture = INVALID_BUFFER_SLOT;
+ returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
+ }
+
+ // look for a free buffer to give to the client
+ found = INVALID_BUFFER_SLOT;
+ foundSync = INVALID_BUFFER_SLOT;
+ dequeuedCount = 0;
+ for (int i = 0; i < mBufferCount; i++) {
+ const int state = mSlots[i].mBufferState;
+ if (state == BufferSlot::DEQUEUED) {
+ dequeuedCount++;
+ }
+ if (state == BufferSlot::FREE || i == mCurrentTexture) {
+ foundSync = i;
+ if (i != mCurrentTexture) {
+ found = i;
+ break;
+ }
+ }
+ }
+
+ // clients are not allowed to dequeue more than one buffer
+ // if they didn't set a buffer count.
+ if (!mClientBufferCount && dequeuedCount) {
+ return -EINVAL;
+ }
+
+ // See whether a buffer has been queued since the last setBufferCount so
+ // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
+ bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT;
+ if (bufferHasBeenQueued) {
+ // make sure the client is not trying to dequeue more buffers
+ // than allowed.
+ const int avail = mBufferCount - (dequeuedCount+1);
+ if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
+ LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
+ MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
+ dequeuedCount);
+ return -EBUSY;
+ }
+ }
+
+ // we're in synchronous mode and didn't find a buffer, we need to wait
+ // for for some buffers to be consumed
+ tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
+ if (tryAgain) {
+ mDequeueCondition.wait(mMutex);
+ }
+ }
+
+ if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
+ // foundSync guaranteed to be != INVALID_BUFFER_SLOT
+ found = foundSync;
+ }
+
+ if (found == INVALID_BUFFER_SLOT) {
+ return -EBUSY;
+ }
+
+ const int buf = found;
+ *outBuf = found;
+
+ const bool useDefaultSize = !w && !h;
+ if (useDefaultSize) {
+ // use the default size
+ w = mDefaultWidth;
+ h = mDefaultHeight;
+ }
+
+ const bool updateFormat = (format != 0);
+ if (!updateFormat) {
+ // keep the current (or default) format
+ format = mPixelFormat;
+ }
+
+ // buffer is now in DEQUEUED (but can also be current at the same time,
+ // if we're in synchronous mode)
+ mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
+
+ const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
+ if ((buffer == NULL) ||
+ (uint32_t(buffer->width) != w) ||
+ (uint32_t(buffer->height) != h) ||
+ (uint32_t(buffer->format) != format) ||
+ ((uint32_t(buffer->usage) & usage) != usage))
+ {
+ usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+ sp<GraphicBuffer> graphicBuffer(
+ mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
+ if (graphicBuffer == 0) {
+ LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
+ return NO_MEMORY;
+ }
+ if (updateFormat) {
+ mPixelFormat = format;
+ }
mSlots[buf].mGraphicBuffer = graphicBuffer;
+ mSlots[buf].mRequestBufferCalled = false;
if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
}
- mAllocdBuffers.add(graphicBuffer);
+ returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
}
- return graphicBuffer;
+ return returnFlags;
}
-status_t SurfaceTexture::dequeueBuffer(int *buf) {
- LOGV("SurfaceTexture::dequeueBuffer");
+status_t SurfaceTexture::setSynchronousMode(bool enabled) {
Mutex::Autolock lock(mMutex);
- int found = INVALID_BUFFER_SLOT;
- for (int i = 0; i < mBufferCount; i++) {
- if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
- mSlots[i].mOwnedByClient = true;
- found = i;
- break;
+
+ status_t err = OK;
+ if (!enabled) {
+ // going to asynchronous mode, drain the queue
+ while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
+ mDequeueCondition.wait(mMutex);
}
}
- if (found == INVALID_BUFFER_SLOT) {
- return -EBUSY;
+
+ if (mSynchronousMode != enabled) {
+ // - if we're going to asynchronous mode, the queue is guaranteed to be
+ // empty here
+ // - if the client set the number of buffers, we're guaranteed that
+ // we have at least 3 (because we don't allow less)
+ mSynchronousMode = enabled;
+ mDequeueCondition.signal();
}
- *buf = found;
- return OK;
+ return err;
}
-status_t SurfaceTexture::queueBuffer(int buf) {
+status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
LOGV("SurfaceTexture::queueBuffer");
- Mutex::Autolock lock(mMutex);
- if (buf < 0 || mBufferCount <= buf) {
- LOGE("queueBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return -EINVAL;
- } else if (!mSlots[buf].mOwnedByClient) {
- LOGE("queueBuffer: slot %d is not owned by the client", buf);
- return -EINVAL;
- } else if (mSlots[buf].mGraphicBuffer == 0) {
- LOGE("queueBuffer: slot %d was enqueued without requesting a buffer",
- buf);
- return -EINVAL;
- }
- mSlots[buf].mOwnedByClient = false;
- mLastQueued = buf;
- mLastQueuedCrop = mNextCrop;
- mLastQueuedTransform = mNextTransform;
- if (mFrameAvailableListener != 0) {
- mFrameAvailableListener->onFrameAvailable();
+
+ sp<FrameAvailableListener> listener;
+
+ { // scope for the lock
+ Mutex::Autolock lock(mMutex);
+ if (buf < 0 || buf >= mBufferCount) {
+ LOGE("queueBuffer: slot index out of range [0, %d]: %d",
+ mBufferCount, buf);
+ return -EINVAL;
+ } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+ LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
+ buf, mSlots[buf].mBufferState);
+ return -EINVAL;
+ } else if (buf == mCurrentTexture) {
+ LOGE("queueBuffer: slot %d is current!", buf);
+ return -EINVAL;
+ } else if (!mSlots[buf].mRequestBufferCalled) {
+ LOGE("queueBuffer: slot %d was enqueued without requesting a "
+ "buffer", buf);
+ return -EINVAL;
+ }
+
+ if (mQueue.empty()) {
+ listener = mFrameAvailableListener;
+ }
+
+ if (mSynchronousMode) {
+ // in synchronous mode we queue all buffers in a FIFO
+ mQueue.push_back(buf);
+ } else {
+ // in asynchronous mode we only keep the most recent buffer
+ if (mQueue.empty()) {
+ mQueue.push_back(buf);
+ } else {
+ Fifo::iterator front(mQueue.begin());
+ // buffer currently queued is freed
+ mSlots[*front].mBufferState = BufferSlot::FREE;
+ // and we record the new buffer index in the queued list
+ *front = buf;
+ }
+ }
+
+ mSlots[buf].mBufferState = BufferSlot::QUEUED;
+ mSlots[buf].mCrop = mNextCrop;
+ mSlots[buf].mTransform = mNextTransform;
+ mSlots[buf].mTimestamp = timestamp;
+ mDequeueCondition.signal();
+ } // scope for the lock
+
+ // call back without lock held
+ if (listener != 0) {
+ listener->onFrameAvailable();
}
return OK;
}
@@ -181,15 +449,17 @@ status_t SurfaceTexture::queueBuffer(int buf) {
void SurfaceTexture::cancelBuffer(int buf) {
LOGV("SurfaceTexture::cancelBuffer");
Mutex::Autolock lock(mMutex);
- if (buf < 0 || mBufferCount <= buf) {
- LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
- buf);
+ if (buf < 0 || buf >= mBufferCount) {
+ LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
+ mBufferCount, buf);
return;
- } else if (!mSlots[buf].mOwnedByClient) {
- LOGE("cancelBuffer: slot %d is not owned by the client", buf);
+ } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+ LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
+ buf, mSlots[buf].mBufferState);
return;
}
- mSlots[buf].mOwnedByClient = false;
+ mSlots[buf].mBufferState = BufferSlot::FREE;
+ mDequeueCondition.signal();
}
status_t SurfaceTexture::setCrop(const Rect& crop) {
@@ -208,50 +478,125 @@ status_t SurfaceTexture::setTransform(uint32_t transform) {
status_t SurfaceTexture::updateTexImage() {
LOGV("SurfaceTexture::updateTexImage");
+
Mutex::Autolock lock(mMutex);
- // We always bind the texture even if we don't update its contents.
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
+ int buf = mCurrentTexture;
+ if (!mQueue.empty()) {
+ // in asynchronous mode the list is guaranteed to be one buffer deep,
+ // while in synchronous mode we use the oldest buffer
+ Fifo::iterator front(mQueue.begin());
+ buf = *front;
+ mQueue.erase(front);
+ if (mQueue.isEmpty()) {
+ mDequeueCondition.signal();
+ }
+ }
- // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
+ // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT,
// so this check will fail until a buffer gets queued.
- if (mCurrentTexture != mLastQueued) {
+ if (mCurrentTexture != buf) {
// Update the GL texture object.
- EGLImageKHR image = mSlots[mLastQueued].mEglImage;
+ EGLImageKHR image = mSlots[buf].mEglImage;
if (image == EGL_NO_IMAGE_KHR) {
EGLDisplay dpy = eglGetCurrentDisplay();
- sp<GraphicBuffer> graphicBuffer = mSlots[mLastQueued].mGraphicBuffer;
- image = createImage(dpy, graphicBuffer);
- mSlots[mLastQueued].mEglImage = image;
- mSlots[mLastQueued].mEglDisplay = dpy;
+ image = createImage(dpy, mSlots[buf].mGraphicBuffer);
+ mSlots[buf].mEglImage = image;
+ mSlots[buf].mEglDisplay = dpy;
+ if (image == EGL_NO_IMAGE_KHR) {
+ // NOTE: if dpy was invalid, createImage() is guaranteed to
+ // fail. so we'd end up here.
+ return -EINVAL;
+ }
}
GLint error;
while ((error = glGetError()) != GL_NO_ERROR) {
- LOGE("GL error cleared before updating SurfaceTexture: %#04x", error);
+ LOGW("updateTexImage: clearing GL error: %#04x", error);
+ }
+
+ GLenum target = getTextureTarget(mSlots[buf].mGraphicBuffer->format);
+ if (target != mCurrentTextureTarget) {
+ glDeleteTextures(1, &mTexName);
}
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
+ glBindTexture(target, mTexName);
+ glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image);
+
bool failed = false;
while ((error = glGetError()) != GL_NO_ERROR) {
LOGE("error binding external texture image %p (slot %d): %#04x",
- image, mLastQueued, error);
+ image, buf, error);
failed = true;
}
if (failed) {
return -EINVAL;
}
+ if (mCurrentTexture != INVALID_BUFFER_SLOT) {
+ // the current buffer becomes FREE if it was still in the queued
+ // state. If it has already been given to the client
+ // (synchronous mode), then it stays in DEQUEUED state.
+ if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
+ mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
+ }
+
// Update the SurfaceTexture state.
- mCurrentTexture = mLastQueued;
- mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
- mCurrentCrop = mLastQueuedCrop;
- mCurrentTransform = mLastQueuedTransform;
+ mCurrentTexture = buf;
+ mCurrentTextureTarget = target;
+ mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
+ mCurrentCrop = mSlots[buf].mCrop;
+ mCurrentTransform = mSlots[buf].mTransform;
+ mCurrentTimestamp = mSlots[buf].mTimestamp;
+ mDequeueCondition.signal();
+ } else {
+ // We always bind the texture even if we don't update its contents.
+ glBindTexture(mCurrentTextureTarget, mTexName);
}
return OK;
}
+size_t SurfaceTexture::getQueuedCount() const {
+ Mutex::Autolock lock(mMutex);
+ return mQueue.size();
+}
+
+bool SurfaceTexture::isExternalFormat(uint32_t format)
+{
+ switch (format) {
+ // supported YUV formats
+ case HAL_PIXEL_FORMAT_YV12:
+ // Legacy/deprecated YUV formats
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ return true;
+ }
+
+ // Any OEM format needs to be considered
+ if (format>=0x100 && format<=0x1FF)
+ return true;
+
+ return false;
+}
+
+GLenum SurfaceTexture::getTextureTarget(uint32_t format)
+{
+ GLenum target = GL_TEXTURE_2D;
+#if defined(GL_OES_EGL_image_external)
+ if (isExternalFormat(format)) {
+ target = GL_TEXTURE_EXTERNAL_OES;
+ }
+#endif
+ return target;
+}
+
+GLenum SurfaceTexture::getCurrentTextureTarget() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentTextureTarget;
+}
+
void SurfaceTexture::getTransformMatrix(float mtx[16]) {
- LOGV("SurfaceTexture::updateTexImage");
+ LOGV("SurfaceTexture::getTransformMatrix");
Mutex::Autolock lock(mMutex);
float xform[16];
@@ -304,10 +649,10 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) {
} else {
tx = 0.0f;
}
- if (mCurrentCrop.right < buf->getWidth()) {
+ if (mCurrentCrop.right < int32_t(buf->getWidth())) {
xshrink++;
}
- if (mCurrentCrop.bottom < buf->getHeight()) {
+ if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
float(buf->getHeight());
yshrink++;
@@ -342,6 +687,12 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) {
mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
}
+nsecs_t SurfaceTexture::getTimestamp() {
+ LOGV("SurfaceTexture::getTimestamp");
+ Mutex::Autolock lock(mMutex);
+ return mCurrentTimestamp;
+}
+
void SurfaceTexture::setFrameAvailableListener(
const sp<FrameAvailableListener>& l) {
LOGV("SurfaceTexture::setFrameAvailableListener");
@@ -357,26 +708,13 @@ sp<IBinder> SurfaceTexture::getAllocator() {
void SurfaceTexture::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].mGraphicBuffer = 0;
- mSlots[i].mOwnedByClient = false;
+ mSlots[i].mBufferState = BufferSlot::FREE;
if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
}
}
-
- int exceptBuf = -1;
- for (size_t i = 0; i < mAllocdBuffers.size(); i++) {
- if (mAllocdBuffers[i] == mCurrentTextureBuf) {
- exceptBuf = i;
- break;
- }
- }
- mAllocdBuffers.clear();
- if (exceptBuf >= 0) {
- mAllocdBuffers.add(mCurrentTextureBuf);
- }
- mGraphicBufferAlloc->freeAllGraphicBuffersExcept(exceptBuf);
}
EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
@@ -388,16 +726,119 @@ EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
};
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
- EGLint error = eglGetError();
- if (error != EGL_SUCCESS) {
+ if (image == EGL_NO_IMAGE_KHR) {
+ EGLint error = eglGetError();
LOGE("error creating EGLImage: %#x", error);
- } else if (image == EGL_NO_IMAGE_KHR) {
- LOGE("no error reported, but no image was returned by "
- "eglCreateImageKHR");
}
return image;
}
+sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentTextureBuf;
+}
+
+Rect SurfaceTexture::getCurrentCrop() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentCrop;
+}
+
+uint32_t SurfaceTexture::getCurrentTransform() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentTransform;
+}
+
+int SurfaceTexture::query(int what, int* outValue)
+{
+ Mutex::Autolock lock(mMutex);
+ int value;
+ switch (what) {
+ case NATIVE_WINDOW_WIDTH:
+ value = mDefaultWidth;
+ if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
+ value = mCurrentTextureBuf->width;
+ break;
+ case NATIVE_WINDOW_HEIGHT:
+ value = mDefaultHeight;
+ if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
+ value = mCurrentTextureBuf->height;
+ break;
+ case NATIVE_WINDOW_FORMAT:
+ value = mPixelFormat;
+ break;
+ case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+ value = mSynchronousMode ?
+ (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+ outValue[0] = value;
+ return NO_ERROR;
+}
+
+void SurfaceTexture::dump(String8& result) const
+{
+ char buffer[1024];
+ dump(result, "", buffer, 1024);
+}
+
+void SurfaceTexture::dump(String8& result, const char* prefix,
+ char* buffer, size_t SIZE) const
+{
+ Mutex::Autolock _l(mMutex);
+ snprintf(buffer, SIZE,
+ "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
+ "mPixelFormat=%d, mTexName=%d\n",
+ prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
+ mPixelFormat, mTexName);
+ result.append(buffer);
+
+ String8 fifo;
+ int fifoSize = 0;
+ Fifo::const_iterator i(mQueue.begin());
+ while (i != mQueue.end()) {
+ snprintf(buffer, SIZE, "%02d ", *i++);
+ fifoSize++;
+ fifo.append(buffer);
+ }
+
+ snprintf(buffer, SIZE,
+ "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d, target=0x%04x}\n"
+ "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
+ ,
+ prefix, mCurrentCrop.left,
+ mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
+ mCurrentTransform, mCurrentTexture, mCurrentTextureTarget,
+ prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
+ mCurrentTransform, fifoSize, fifo.string()
+ );
+ result.append(buffer);
+
+ struct {
+ const char * operator()(int state) const {
+ switch (state) {
+ case BufferSlot::DEQUEUED: return "DEQUEUED";
+ case BufferSlot::QUEUED: return "QUEUED";
+ case BufferSlot::FREE: return "FREE";
+ default: return "Unknown";
+ }
+ }
+ } stateName;
+
+ for (int i=0 ; i<mBufferCount ; i++) {
+ const BufferSlot& slot(mSlots[i]);
+ snprintf(buffer, SIZE,
+ "%s%s[%02d] state=%-8s, crop=[%d,%d,%d,%d], transform=0x%02x, "
+ "timestamp=%lld\n",
+ prefix, (i==mCurrentTexture)?">":" ", i, stateName(slot.mBufferState),
+ slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, slot.mCrop.bottom,
+ slot.mTransform, slot.mTimestamp
+ );
+ result.append(buffer);
+ }
+}
+
static void mtxMul(float out[16], const float a[16], const float b[16]) {
out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 7f1d9cb..c20fcf2 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -25,8 +25,11 @@ namespace android {
SurfaceTextureClient::SurfaceTextureClient(
const sp<ISurfaceTexture>& surfaceTexture):
- mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
- mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
+ mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0),
+ mReqHeight(0), mReqFormat(0), mReqUsage(0),
+ mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0),
+ mQueryWidth(0), mQueryHeight(0), mQueryFormat(0),
+ mMutex() {
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
@@ -36,6 +39,9 @@ SurfaceTextureClient::SurfaceTextureClient(
ANativeWindow::query = query;
ANativeWindow::perform = perform;
+ const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
+ const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
+
// Get a reference to the allocator.
mAllocator = mSurfaceTexture->getAllocator();
}
@@ -50,31 +56,32 @@ int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) {
}
int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window,
- android_native_buffer_t** buffer) {
+ ANativeWindowBuffer** buffer) {
SurfaceTextureClient* c = getSelf(window);
return c->dequeueBuffer(buffer);
}
int SurfaceTextureClient::cancelBuffer(ANativeWindow* window,
- android_native_buffer_t* buffer) {
+ ANativeWindowBuffer* buffer) {
SurfaceTextureClient* c = getSelf(window);
return c->cancelBuffer(buffer);
}
int SurfaceTextureClient::lockBuffer(ANativeWindow* window,
- android_native_buffer_t* buffer) {
+ ANativeWindowBuffer* buffer) {
SurfaceTextureClient* c = getSelf(window);
return c->lockBuffer(buffer);
}
int SurfaceTextureClient::queueBuffer(ANativeWindow* window,
- android_native_buffer_t* buffer) {
+ ANativeWindowBuffer* buffer) {
SurfaceTextureClient* c = getSelf(window);
return c->queueBuffer(buffer);
}
-int SurfaceTextureClient::query(ANativeWindow* window, int what, int* value) {
- SurfaceTextureClient* c = getSelf(window);
+int SurfaceTextureClient::query(const ANativeWindow* window,
+ int what, int* value) {
+ const SurfaceTextureClient* c = getSelf(window);
return c->query(what, value);
}
@@ -86,29 +93,48 @@ int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) {
}
int SurfaceTextureClient::setSwapInterval(int interval) {
- return INVALID_OPERATION;
+ // EGL specification states:
+ // interval is silently clamped to minimum and maximum implementation
+ // dependent values before being stored.
+ // Although we don't have to, we apply the same logic here.
+
+ if (interval < minSwapInterval)
+ interval = minSwapInterval;
+
+ if (interval > maxSwapInterval)
+ interval = maxSwapInterval;
+
+ status_t res = mSurfaceTexture->setSynchronousMode(interval ? true : false);
+
+ return res;
}
int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
LOGV("SurfaceTextureClient::dequeueBuffer");
Mutex::Autolock lock(mMutex);
int buf = -1;
- status_t err = mSurfaceTexture->dequeueBuffer(&buf);
- if (err < 0) {
- LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
- return err;
+ status_t result = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,
+ mReqFormat, mReqUsage);
+ if (result < 0) {
+ LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
+ "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
+ result);
+ return result;
}
sp<GraphicBuffer>& gbuf(mSlots[buf]);
- if (gbuf == 0 || gbuf->getWidth() != mReqWidth ||
- gbuf->getHeight() != mReqHeight ||
- uint32_t(gbuf->getPixelFormat()) != mReqFormat ||
- (gbuf->getUsage() & mReqUsage) != mReqUsage) {
- gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight,
- mReqFormat, mReqUsage);
+ if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
+ freeAllBuffers();
+ }
+
+ if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
+ gbuf = mSurfaceTexture->requestBuffer(buf);
if (gbuf == 0) {
LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
return NO_MEMORY;
}
+ mQueryWidth = gbuf->width;
+ mQueryHeight = gbuf->height;
+ mQueryFormat = gbuf->format;
}
*buffer = gbuf.get();
return OK;
@@ -135,40 +161,36 @@ int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
LOGV("SurfaceTextureClient::queueBuffer");
Mutex::Autolock lock(mMutex);
+ int64_t timestamp;
+ if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
+ timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms",
+ timestamp / 1000000.f);
+ } else {
+ timestamp = mTimestamp;
+ }
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
if (mSlots[i]->handle == buffer->handle) {
- return mSurfaceTexture->queueBuffer(i);
+ return mSurfaceTexture->queueBuffer(i, timestamp);
}
}
LOGE("queueBuffer: unknown buffer queued");
return BAD_VALUE;
}
-int SurfaceTextureClient::query(int what, int* value) {
+int SurfaceTextureClient::query(int what, int* value) const {
LOGV("SurfaceTextureClient::query");
- Mutex::Autolock lock(mMutex);
switch (what) {
- case NATIVE_WINDOW_WIDTH:
- case NATIVE_WINDOW_HEIGHT:
- // XXX: How should SurfaceTexture behave if setBuffersGeometry didn't
- // override the size?
- *value = 0;
- return NO_ERROR;
- case NATIVE_WINDOW_FORMAT:
- *value = DEFAULT_FORMAT;
- return NO_ERROR;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- *value = MIN_UNDEQUEUED_BUFFERS;
- return NO_ERROR;
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
- // SurfaceTextureClient currently never queues frames to SurfaceFlinger.
+ // TODO: this is not needed anymore
*value = 0;
return NO_ERROR;
case NATIVE_WINDOW_CONCRETE_TYPE:
+ // TODO: this is not needed anymore
*value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
return NO_ERROR;
}
- return BAD_VALUE;
+ return mSurfaceTexture->query(what, value);
}
int SurfaceTextureClient::perform(int operation, va_list args)
@@ -196,6 +218,9 @@ int SurfaceTextureClient::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
res = dispatchSetBuffersTransform(args);
break;
+ case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+ res = dispatchSetBuffersTimestamp(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -240,18 +265,56 @@ int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
return setBuffersTransform(transform);
}
+int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
+ int64_t timestamp = va_arg(args, int64_t);
+ return setBuffersTimestamp(timestamp);
+}
+
int SurfaceTextureClient::connect(int api) {
LOGV("SurfaceTextureClient::connect");
- // XXX: Implement this!
- return INVALID_OPERATION;
+ Mutex::Autolock lock(mMutex);
+ int err = NO_ERROR;
+ switch (api) {
+ case NATIVE_WINDOW_API_EGL:
+ if (mConnectedApi) {
+ err = -EINVAL;
+ } else {
+ mConnectedApi = api;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ return err;
}
int SurfaceTextureClient::disconnect(int api) {
LOGV("SurfaceTextureClient::disconnect");
- // XXX: Implement this!
- return INVALID_OPERATION;
+ Mutex::Autolock lock(mMutex);
+ int err = NO_ERROR;
+ switch (api) {
+ case NATIVE_WINDOW_API_EGL:
+ if (mConnectedApi == api) {
+ mConnectedApi = 0;
+ } else {
+ err = -EINVAL;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ return err;
}
+int SurfaceTextureClient::getConnectedApi() const
+{
+ Mutex::Autolock lock(mMutex);
+ return mConnectedApi;
+}
+
+
int SurfaceTextureClient::setUsage(uint32_t reqUsage)
{
LOGV("SurfaceTextureClient::setUsage");
@@ -323,6 +386,14 @@ int SurfaceTextureClient::setBuffersTransform(int transform)
return err;
}
+int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
+{
+ LOGV("SurfaceTextureClient::setBuffersTimestamp");
+ Mutex::Autolock lock(mMutex);
+ mTimestamp = timestamp;
+ return NO_ERROR;
+}
+
void SurfaceTextureClient::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i] = 0;
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index 7516299..8d3a9b5 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -9,6 +9,7 @@ LOCAL_MODULE := SurfaceTexture_test
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := \
+ Surface_test.cpp \
SurfaceTextureClient_test.cpp \
SurfaceTexture_test.cpp \
@@ -20,7 +21,6 @@ LOCAL_SHARED_LIBRARIES := \
libcutils \
libgui \
libstlport \
- libsurfaceflinger_client \
libui \
libutils \
@@ -36,9 +36,6 @@ LOCAL_C_INCLUDES := \
include $(BUILD_EXECUTABLE)
-# Build the manual test programs.
-include $(call all-subdir-makefiles)
-
endif
# Include subdirectory makefiles
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 94b05bc..2f704c8 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -17,23 +17,78 @@
#include <EGL/egl.h>
#include <gtest/gtest.h>
#include <gui/SurfaceTextureClient.h>
+#include <utils/threads.h>
namespace android {
class SurfaceTextureClientTest : public ::testing::Test {
protected:
+ SurfaceTextureClientTest():
+ mEglDisplay(EGL_NO_DISPLAY),
+ mEglSurface(EGL_NO_SURFACE),
+ mEglContext(EGL_NO_CONTEXT) {
+ }
+
virtual void SetUp() {
mST = new SurfaceTexture(123);
mSTC = new SurfaceTextureClient(mST);
+
+ // We need a valid GL context so we can test updateTexImage()
+ // This initializes EGL and create a dummy GL context with a
+ // pbuffer render target.
+ mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+
+ EGLint majorVersion, minorVersion;
+ EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ EGLConfig myConfig;
+ EGLint numConfigs = 0;
+ EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(),
+ &myConfig, 1, &numConfigs));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ EGLint pbufferAttribs[] = {
+ EGL_WIDTH, 16,
+ EGL_HEIGHT, 16,
+ EGL_NONE };
+ mEglSurface = eglCreatePbufferSurface(mEglDisplay, myConfig, pbufferAttribs);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+
+ mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, 0);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
+
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
}
virtual void TearDown() {
mST.clear();
mSTC.clear();
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(mEglDisplay, mEglContext);
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ eglTerminate(mEglDisplay);
+ }
+
+ virtual EGLint const* getConfigAttribs() {
+ static EGLint sDefaultConfigAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_NONE
+ };
+
+ return sDefaultConfigAttribs;
}
sp<SurfaceTexture> mST;
sp<SurfaceTextureClient> mSTC;
+ EGLDisplay mEglDisplay;
+ EGLSurface mEglSurface;
+ EGLContext mEglContext;
};
TEST_F(SurfaceTextureClientTest, GetISurfaceTextureIsNotNull) {
@@ -64,7 +119,7 @@ TEST_F(SurfaceTextureClientTest, ANativeWindowLockFails) {
ASSERT_EQ(BAD_VALUE, ANativeWindow_lock(anw.get(), &buf, NULL));
}
-TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceFails) {
+TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) {
sp<ANativeWindow> anw(mSTC);
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -94,10 +149,369 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceFails) {
EGLSurface eglSurface = eglCreateWindowSurface(dpy, myConfig, anw.get(),
NULL);
- ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
- ASSERT_EQ(EGL_BAD_NATIVE_WINDOW, eglGetError());
+ EXPECT_NE(EGL_NO_SURFACE, eglSurface);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
eglTerminate(dpy);
}
+TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) {
+ sp<ANativeWindow> anw(mSTC);
+
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), -1, 0, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, -1, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, -1));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), -1, -1, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, 8, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 8, 0, 0));
+}
+
+TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
+ sp<ANativeWindow> anw(mSTC);
+ ANativeWindowBuffer* buf;
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(1, buf->width);
+ EXPECT_EQ(1, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
+ sp<ANativeWindow> anw(mSTC);
+ ANativeWindowBuffer* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
+ sp<ANativeWindow> anw(mSTC);
+ ANativeWindowBuffer* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(1, buf->width);
+ EXPECT_EQ(1, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
+ sp<ANativeWindow> anw(mSTC);
+ ANativeWindowBuffer* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
+ sp<ANativeWindow> anw(mSTC);
+ ANativeWindowBuffer* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(1, buf->width);
+ EXPECT_EQ(1, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
+ sp<ANativeWindow> anw(mSTC);
+ ANativeWindowBuffer* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(1, buf->width);
+ EXPECT_EQ(1, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ ANativeWindowBuffer* buf;
+ EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ ANativeWindowBuffer* buf[2];
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+ EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_EQ(16, buf[0]->width);
+ EXPECT_EQ(16, buf[1]->width);
+ EXPECT_EQ(8, buf[0]->height);
+ EXPECT_EQ(8, buf[1]->height);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ ANativeWindowBuffer* buf[2];
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+ EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_EQ(16, buf[0]->width);
+ EXPECT_EQ(16, buf[1]->width);
+ EXPECT_EQ(8, buf[0]->height);
+ EXPECT_EQ(8, buf[1]->height);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 12, 24, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_EQ(12, buf[0]->width);
+ EXPECT_EQ(12, buf[1]->width);
+ EXPECT_EQ(24, buf[0]->height);
+ EXPECT_EQ(24, buf[1]->height);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, st->setSynchronousMode(false));
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(OK, st->updateTexImage());
+
+ ASSERT_EQ(OK, st->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(OK, st->updateTexImage());
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, st->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_NE(buf[1], buf[2]);
+ EXPECT_NE(buf[2], buf[0]);
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, st->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_NE(buf[1], buf[2]);
+ EXPECT_NE(buf[2], buf[0]);
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, st->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
+
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ EXPECT_NE(buf[1], buf[2]);
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+}
+
+// XXX: We currently have no hardware that properly handles dequeuing the
+// buffer that is currently bound to the texture.
+TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf[3];
+ android_native_buffer_t* firstBuf;
+ ASSERT_EQ(OK, st->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &firstBuf));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), firstBuf));
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), firstBuf);
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_NE(buf[1], buf[2]);
+ EXPECT_NE(buf[2], buf[0]);
+ EXPECT_EQ(firstBuf, buf[2]);
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, st->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+
+ // We should be able to dequeue all the buffers before we've queued any.
+ EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[2]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+
+ EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+
+ EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+
+ // Once we've queued a buffer, however we should not be able to dequeue more
+ // than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case.
+ EXPECT_EQ(-EBUSY, anw->dequeueBuffer(anw.get(), &buf[1]));
+
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[2]));
+}
+
+// XXX: This is not expected to pass until the synchronization hacks are removed
+// from the SurfaceTexture class.
+TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+
+ class MyThread : public Thread {
+ sp<SurfaceTexture> st;
+ EGLContext ctx;
+ EGLSurface sur;
+ EGLDisplay dpy;
+ bool mBufferRetired;
+ Mutex mLock;
+ virtual bool threadLoop() {
+ eglMakeCurrent(dpy, sur, sur, ctx);
+ usleep(20000);
+ Mutex::Autolock _l(mLock);
+ st->updateTexImage();
+ mBufferRetired = true;
+ eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ return false;
+ }
+ public:
+ MyThread(const sp<SurfaceTexture>& st)
+ : st(st), mBufferRetired(false) {
+ ctx = eglGetCurrentContext();
+ sur = eglGetCurrentSurface(EGL_DRAW);
+ dpy = eglGetCurrentDisplay();
+ eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
+ ~MyThread() {
+ eglMakeCurrent(dpy, sur, sur, ctx);
+ }
+ void bufferDequeued() {
+ Mutex::Autolock _l(mLock);
+ EXPECT_EQ(true, mBufferRetired);
+ }
+ };
+
+ android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, st->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+ // dequeue/queue/update so we have a current buffer
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+ st->updateTexImage();
+
+ MyThread* thread = new MyThread(st);
+ sp<Thread> threadBase(thread);
+
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+ thread->run();
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+ thread->bufferDequeued();
+ thread->requestExitAndWait();
+}
+
}
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 4184463..8747ba5 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -76,7 +76,7 @@ protected:
mComposerClient = new SurfaceComposerClient;
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
- mSurfaceControl = mComposerClient->createSurface(getpid(),
+ mSurfaceControl = mComposerClient->createSurface(
String8("Test Surface"), 0,
getSurfaceWidth(), getSurfaceHeight(),
PIXEL_FORMAT_RGB_888, 0);
@@ -476,7 +476,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
- android_native_buffer_t* anb;
+ ANativeWindowBuffer* anb;
ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
ASSERT_TRUE(anb != NULL);
@@ -524,7 +524,7 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledYV12BufferPow2) {
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
- android_native_buffer_t* anb;
+ ANativeWindowBuffer* anb;
ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
ASSERT_TRUE(anb != NULL);
@@ -583,7 +583,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
- android_native_buffer_t* anb;
+ ANativeWindowBuffer* anb;
ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
ASSERT_TRUE(anb != NULL);
diff --git a/libs/surfaceflinger_client/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index fd07479..35c8640 100644
--- a/libs/surfaceflinger_client/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -30,7 +30,7 @@ protected:
mComposerClient = new SurfaceComposerClient;
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
- mSurfaceControl = mComposerClient->createSurface(getpid(),
+ mSurfaceControl = mComposerClient->createSurface(
String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGB_888, 0);
ASSERT_TRUE(mSurfaceControl != NULL);
@@ -93,7 +93,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) {
ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(),
GRALLOC_USAGE_PROTECTED));
ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3));
- android_native_buffer_t* buf = 0;
+ ANativeWindowBuffer* buf = 0;
for (int i = 0; i < 4; i++) {
// Loop to make sure SurfaceFlinger has retired a protected buffer.
ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index f4a0161..a98e4cd 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -9,6 +9,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
FontRenderer.cpp \
GammaFontRenderer.cpp \
Caches.cpp \
+ DisplayListLogBuffer.cpp \
DisplayListRenderer.cpp \
FboCache.cpp \
GradientCache.cpp \
@@ -42,7 +43,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui
LOCAL_MODULE := libhwui
LOCAL_MODULE_TAGS := optional
- LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 4f5edd5..b0d8cf9 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "OpenGLRenderer"
#include <utils/Log.h>
+#include <utils/String8.h>
#include "Caches.h"
#include "Properties.h"
@@ -69,30 +70,43 @@ Caches::~Caches() {
///////////////////////////////////////////////////////////////////////////////
void Caches::dumpMemoryUsage() {
- LOGD("Current memory usage / total memory usage (bytes):");
- LOGD(" TextureCache %8d / %8d", textureCache.getSize(), textureCache.getMaxSize());
- LOGD(" LayerCache %8d / %8d", layerCache.getSize(), layerCache.getMaxSize());
- LOGD(" GradientCache %8d / %8d", gradientCache.getSize(), gradientCache.getMaxSize());
- LOGD(" PathCache %8d / %8d", pathCache.getSize(), pathCache.getMaxSize());
- LOGD(" CircleShapeCache %8d / %8d",
+ String8 stringLog;
+ dumpMemoryUsage(stringLog);
+ LOGD("%s", stringLog.string());
+ delete stringLog;
+}
+
+void Caches::dumpMemoryUsage(String8 &log) {
+ log.appendFormat("Current memory usage / total memory usage (bytes):\n");
+ log.appendFormat(" TextureCache %8d / %8d\n",
+ textureCache.getSize(), textureCache.getMaxSize());
+ log.appendFormat(" LayerCache %8d / %8d\n",
+ layerCache.getSize(), layerCache.getMaxSize());
+ log.appendFormat(" GradientCache %8d / %8d\n",
+ gradientCache.getSize(), gradientCache.getMaxSize());
+ log.appendFormat(" PathCache %8d / %8d\n",
+ pathCache.getSize(), pathCache.getMaxSize());
+ log.appendFormat(" CircleShapeCache %8d / %8d\n",
circleShapeCache.getSize(), circleShapeCache.getMaxSize());
- LOGD(" OvalShapeCache %8d / %8d",
+ log.appendFormat(" OvalShapeCache %8d / %8d\n",
ovalShapeCache.getSize(), ovalShapeCache.getMaxSize());
- LOGD(" RoundRectShapeCache %8d / %8d",
+ log.appendFormat(" RoundRectShapeCache %8d / %8d\n",
roundRectShapeCache.getSize(), roundRectShapeCache.getMaxSize());
- LOGD(" RectShapeCache %8d / %8d",
+ log.appendFormat(" RectShapeCache %8d / %8d\n",
rectShapeCache.getSize(), rectShapeCache.getMaxSize());
- LOGD(" ArcShapeCache %8d / %8d",
+ log.appendFormat(" ArcShapeCache %8d / %8d\n",
arcShapeCache.getSize(), arcShapeCache.getMaxSize());
- LOGD(" TextDropShadowCache %8d / %8d", dropShadowCache.getSize(),
+ log.appendFormat(" TextDropShadowCache %8d / %8d\n", dropShadowCache.getSize(),
dropShadowCache.getMaxSize());
for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
const uint32_t size = fontRenderer.getFontRendererSize(i);
- LOGD(" FontRenderer %d %8d / %8d", i, size, size);
+ log.appendFormat(" FontRenderer %d %8d / %8d\n", i, size, size);
}
- LOGD("Other:");
- LOGD(" FboCache %8d / %8d", fboCache.getSize(), fboCache.getMaxSize());
- LOGD(" PatchCache %8d / %8d", patchCache.getSize(), patchCache.getMaxSize());
+ log.appendFormat("Other:\n");
+ log.appendFormat(" FboCache %8d / %8d\n",
+ fboCache.getSize(), fboCache.getMaxSize());
+ log.appendFormat(" PatchCache %8d / %8d\n",
+ patchCache.getSize(), patchCache.getMaxSize());
uint32_t total = 0;
total += textureCache.getSize();
@@ -109,9 +123,8 @@ void Caches::dumpMemoryUsage() {
total += fontRenderer.getFontRendererSize(i);
}
- LOGD("Total memory usage:");
- LOGD(" %d bytes, %.2f MB", total, total / 1024.0f / 1024.0f);
- LOGD("\n");
+ log.appendFormat("Total memory usage:\n");
+ log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 0a9335f..596781e 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -60,7 +60,12 @@ static const TextureVertex gMeshVertices[] = {
FV(1.0f, 1.0f, 1.0f, 1.0f)
};
static const GLsizei gMeshStride = sizeof(TextureVertex);
+static const GLsizei gVertexStride = sizeof(Vertex);
+static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex);
+static const GLsizei gAAVertexStride = sizeof(AAVertex);
static const GLsizei gMeshTextureOffset = 2 * sizeof(float);
+static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float);
+static const GLsizei gVertexAALengthOffset = 3 * sizeof(float);
static const GLsizei gMeshCount = 4;
///////////////////////////////////////////////////////////////////////////////
@@ -140,6 +145,7 @@ public:
* Displays the memory usage of each cache and the total sum.
*/
void dumpMemoryUsage();
+ void dumpMemoryUsage(String8& log);
bool blend;
GLenum lastSrcMode;
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 14471bc..2cdc8c3 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -26,7 +26,7 @@
// Turn on to enable memory usage summary on each frame
#define DEBUG_MEMORY_USAGE 0
-// Turn on to enable layers debugging when renderered as regions
+// Turn on to enable layers debugging when rendered as regions
#define DEBUG_LAYERS_AS_REGIONS 0
// Turn on to display debug info about vertex/fragment shaders
@@ -35,8 +35,10 @@
// Turn on to display info about layers
#define DEBUG_LAYERS 0
-// Turn on to display debug infor about 9patch objects
+// Turn on to display debug info about 9patch objects
#define DEBUG_PATCHES 0
+// Turn on to "explode" 9patch objects
+#define DEBUG_EXPLODE_PATCHES 0
// Turn on to display vertex and tex coords data about 9patch objects
// This flag requires DEBUG_PATCHES to be turned on
#define DEBUG_PATCHES_VERTICES 0
diff --git a/libs/hwui/DisplayListLogBuffer.cpp b/libs/hwui/DisplayListLogBuffer.cpp
new file mode 100644
index 0000000..f204644
--- /dev/null
+++ b/libs/hwui/DisplayListLogBuffer.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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 "DisplayListLogBuffer.h"
+
+// BUFFER_SIZE size must be one more than a multiple of COMMAND_SIZE to ensure
+// that mStart always points at the next command, not just the next item
+#define COMMAND_SIZE 2
+#define NUM_COMMANDS 50
+#define BUFFER_SIZE ((NUM_COMMANDS * COMMAND_SIZE) + 1)
+
+/**
+ * DisplayListLogBuffer is a utility class which logs the most recent display
+ * list operations in a circular buffer. The log is process-wide, because we
+ * only care about the most recent operations, not the operations on a per-window
+ * basis for a given activity. The purpose of the log is to provide more debugging
+ * information in a bug report, by telling us not just where a process hung (which
+ * generally is just reported as a stack trace at the Java level) or crashed, but
+ * also what happened immediately before that hang or crash. This may help track down
+ * problems in the native rendering code or driver interaction related to the display
+ * list operations that led up to the hang or crash.
+ *
+ * The log is implemented as a circular buffer for both space and performance
+ * reasons - we only care about the last several operations to give us context
+ * leading up to the problem, and we don't want to constantly copy data around or do
+ * additional mallocs to keep the most recent operations logged. Only numbers are
+ * logged to make the operation fast. If and when the log is output, we process this
+ * data into meaningful strings.
+ *
+ * There is an assumption about the format of the command (currently 2 ints: the
+ * opcode and the nesting level). If the type of information logged changes (for example,
+ * we may want to save a timestamp), then the size of the buffer and the way the
+ * information is recorded in writeCommand() should change to suit.
+ */
+
+namespace android {
+
+#ifdef USE_OPENGL_RENDERER
+using namespace uirenderer;
+ANDROID_SINGLETON_STATIC_INSTANCE(DisplayListLogBuffer);
+#endif
+
+namespace uirenderer {
+
+
+DisplayListLogBuffer::DisplayListLogBuffer() {
+ mBufferFirst = (int*) malloc(BUFFER_SIZE * sizeof(int));
+ mStart = mBufferFirst;
+ mBufferLast = mBufferFirst + BUFFER_SIZE - 1;
+ mEnd = mStart;
+}
+
+DisplayListLogBuffer::~DisplayListLogBuffer() {
+ free(mBufferFirst);
+}
+
+/**
+ * Called from DisplayListRenderer to output the current buffer into the
+ * specified FILE. This only happens in a dumpsys/bugreport operation.
+ */
+void DisplayListLogBuffer::outputCommands(FILE *file, const char* opNames[])
+{
+ int *tmpBufferPtr = mStart;
+ while (true) {
+ if (tmpBufferPtr == mEnd) {
+ break;
+ }
+ int level = *tmpBufferPtr++;
+ if (tmpBufferPtr > mBufferLast) {
+ tmpBufferPtr = mBufferFirst;
+ }
+ int op = *tmpBufferPtr++;
+ if (tmpBufferPtr > mBufferLast) {
+ tmpBufferPtr = mBufferFirst;
+ }
+ uint32_t count = (level + 1) * 2;
+ char indent[count + 1];
+ for (uint32_t i = 0; i < count; i++) {
+ indent[i] = ' ';
+ }
+ indent[count] = '\0';
+ fprintf(file, "%s%s\n", indent, opNames[op]);
+ }
+}
+
+void DisplayListLogBuffer::writeCommand(int level, int op) {
+ writeInt(level);
+ writeInt(op);
+}
+
+/**
+ * Store the given value in the buffer and increment/wrap the mEnd
+ * and mStart values as appropriate.
+ */
+void DisplayListLogBuffer::writeInt(int value) {
+ *((int*)mEnd) = value;
+ if (mEnd == mBufferLast) {
+ mEnd = mBufferFirst;
+ } else {
+ mEnd++;
+ }
+ if (mEnd == mStart) {
+ mStart++;
+ if (mStart > mBufferLast) {
+ mStart = mBufferFirst;
+ }
+ }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/DisplayListLogBuffer.h b/libs/hwui/DisplayListLogBuffer.h
new file mode 100644
index 0000000..bf16f29
--- /dev/null
+++ b/libs/hwui/DisplayListLogBuffer.h
@@ -0,0 +1,52 @@
+/*
+ * 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_HWUI_DISPLAY_LIST_LOG_BUFFER_H
+#define ANDROID_HWUI_DISPLAY_LIST_LOG_BUFFER_H
+
+#include <utils/Singleton.h>
+#include <stdio.h>
+
+namespace android {
+namespace uirenderer {
+
+class DisplayListLogBuffer: public Singleton<DisplayListLogBuffer> {
+ DisplayListLogBuffer();
+ ~DisplayListLogBuffer();
+
+ friend class Singleton<DisplayListLogBuffer>;
+
+public:
+ void writeCommand(int level, int op);
+ void writeInt(int value);
+ void outputCommands(FILE *file, const char* opNames[]);
+
+ bool isEmpty() {
+ return (mStart == mEnd);
+ }
+
+private:
+ int *mBufferFirst; // where the memory starts
+ int* mStart; // where the current command stream starts
+ int* mEnd; // where the current commands end
+ int* mBufferLast; // where the buffer memory ends
+
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_DISPLAY_LIST_LOG_BUFFER_H
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 868290b..afab26a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -16,11 +16,16 @@
#define LOG_TAG "OpenGLRenderer"
+
+#include "DisplayListLogBuffer.h"
#include "DisplayListRenderer.h"
+#include <utils/String8.h>
+#include "Caches.h"
namespace android {
namespace uirenderer {
+
///////////////////////////////////////////////////////////////////////////////
// Display list
///////////////////////////////////////////////////////////////////////////////
@@ -53,6 +58,7 @@ const char* DisplayList::OP_NAMES[] = {
"DrawArc",
"DrawPath",
"DrawLines",
+ "DrawPoints",
"DrawText",
"ResetShader",
"SetupShader",
@@ -63,6 +69,20 @@ const char* DisplayList::OP_NAMES[] = {
"DrawGLFunction"
};
+void DisplayList::outputLogBuffer(int fd) {
+ DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
+ if (logBuffer.isEmpty()) {
+ return;
+ }
+ String8 cachesLog;
+ Caches::getInstance().dumpMemoryUsage(cachesLog);
+ FILE *file = fdopen(fd, "a");
+ fprintf(file, "\nCaches:\n%s", cachesLog.string());
+ fprintf(file, "\nRecent DisplayList operations\n");
+ logBuffer.outputCommands(file, OP_NAMES);
+ fflush(file);
+}
+
DisplayList::DisplayList(const DisplayListRenderer& recorder) {
initFromDisplayListRenderer(recorder);
}
@@ -92,13 +112,11 @@ void DisplayList::clearResources() {
mPaints.clear();
for (size_t i = 0; i < mPaths.size(); i++) {
- delete mPaths.itemAt(i);
+ SkPath* path = mPaths.itemAt(i);
+ caches.pathCache.remove(path);
+ delete path;
}
mPaths.clear();
- for (size_t i = 0; i < mOriginalPaths.size(); i++) {
- caches.resourceCache.decrementRefcount(mOriginalPaths.itemAt(i));
- }
- mOriginalPaths.clear();
for (size_t i = 0; i < mMatrices.size(); i++) {
delete mMatrices.itemAt(i);
@@ -150,13 +168,6 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
mPaths.add(paths.itemAt(i));
}
- const Vector<SkPath*> &originalPaths = recorder.getOriginalPaths();
- for (size_t i = 0; i < originalPaths.size(); i++) {
- SkPath* path = originalPaths.itemAt(i);
- mOriginalPaths.add(path);
- caches.resourceCache.incrementRefcount(path);
- }
-
const Vector<SkMatrix*> &matrices = recorder.getMatrices();
for (size_t i = 0; i < matrices.size(); i++) {
mMatrices.add(matrices.itemAt(i));
@@ -166,6 +177,331 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
void DisplayList::init() {
}
+/**
+ * This function is a simplified version of replay(), where we simply retrieve and log the
+ * display list. This function should remain in sync with the replay() function.
+ */
+void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
+ TextContainer text;
+
+ uint32_t count = (level + 1) * 2;
+ char indent[count + 1];
+ for (uint32_t i = 0; i < count; i++) {
+ indent[i] = ' ';
+ }
+ indent[count] = '\0';
+ LOGD("%sStart display list (%p)", (char*) indent + 2, this);
+
+ int saveCount = renderer.getSaveCount() - 1;
+
+ mReader.rewind();
+
+ while (!mReader.eof()) {
+ int op = mReader.readInt();
+
+ switch (op) {
+ case DrawGLFunction: {
+ Functor *functor = (Functor *) getInt();
+ LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
+ }
+ break;
+ case Save: {
+ int rendererNum = getInt();
+ LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
+ }
+ break;
+ case Restore: {
+ LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ }
+ break;
+ case RestoreToCount: {
+ int restoreCount = saveCount + getInt();
+ LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
+ }
+ break;
+ case SaveLayer: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ SkPaint* paint = getPaint();
+ int flags = getInt();
+ LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
+ OP_NAMES[op], f1, f2, f3, f4, paint, flags);
+ }
+ break;
+ case SaveLayerAlpha: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ int alpha = getInt();
+ int flags = getInt();
+ LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
+ OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
+ }
+ break;
+ case Translate: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
+ }
+ break;
+ case Rotate: {
+ float rotation = getFloat();
+ LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
+ }
+ break;
+ case Scale: {
+ float sx = getFloat();
+ float sy = getFloat();
+ LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
+ }
+ break;
+ case Skew: {
+ float sx = getFloat();
+ float sy = getFloat();
+ LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
+ }
+ break;
+ case SetMatrix: {
+ SkMatrix* matrix = getMatrix();
+ LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
+ }
+ break;
+ case ConcatMatrix: {
+ SkMatrix* matrix = getMatrix();
+ LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
+ }
+ break;
+ case ClipRect: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ int regionOp = getInt();
+ LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
+ f1, f2, f3, f4, regionOp);
+ }
+ break;
+ case DrawDisplayList: {
+ DisplayList* displayList = getDisplayList();
+ uint32_t width = getUInt();
+ uint32_t height = getUInt();
+ LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op],
+ displayList, width, height, level + 1);
+ renderer.outputDisplayList(displayList, level + 1);
+ }
+ break;
+ case DrawLayer: {
+ Layer* layer = (Layer*) getInt();
+ float x = getFloat();
+ float y = getFloat();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+ layer, x, y, paint);
+ }
+ break;
+ case DrawBitmap: {
+ SkBitmap* bitmap = getBitmap();
+ float x = getFloat();
+ float y = getFloat();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+ bitmap, x, y, paint);
+ }
+ break;
+ case DrawBitmapMatrix: {
+ SkBitmap* bitmap = getBitmap();
+ SkMatrix* matrix = getMatrix();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
+ bitmap, matrix, paint);
+ }
+ break;
+ case DrawBitmapRect: {
+ SkBitmap* bitmap = getBitmap();
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ float f5 = getFloat();
+ float f6 = getFloat();
+ float f7 = getFloat();
+ float f8 = getFloat();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
+ (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
+ }
+ break;
+ case DrawBitmapMesh: {
+ int verticesCount = 0;
+ uint32_t colorsCount = 0;
+ SkBitmap* bitmap = getBitmap();
+ uint32_t meshWidth = getInt();
+ uint32_t meshHeight = getInt();
+ float* vertices = getFloats(verticesCount);
+ bool hasColors = getInt();
+ int* colors = hasColors ? getInts(colorsCount) : NULL;
+ SkPaint* paint = getPaint();
+ LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ }
+ break;
+ case DrawPatch: {
+ int32_t* xDivs = NULL;
+ int32_t* yDivs = NULL;
+ uint32_t* colors = NULL;
+ uint32_t xDivsCount = 0;
+ uint32_t yDivsCount = 0;
+ int8_t numColors = 0;
+ SkBitmap* bitmap = getBitmap();
+ xDivs = getInts(xDivsCount);
+ yDivs = getInts(yDivsCount);
+ colors = getUInts(numColors);
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ getFloat();
+ getFloat();
+ getFloat();
+ getFloat();
+ getPaint();
+ }
+ break;
+ case DrawColor: {
+ int color = getInt();
+ int xferMode = getInt();
+ LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
+ }
+ break;
+ case DrawRect: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+ f1, f2, f3, f4, paint);
+ }
+ break;
+ case DrawRoundRect: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ float f5 = getFloat();
+ float f6 = getFloat();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
+ }
+ break;
+ case DrawCircle: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %.2f, %.2f, %.2f, %p",
+ (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
+ }
+ break;
+ case DrawOval: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
+ }
+ break;
+ case DrawArc: {
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ float f5 = getFloat();
+ float f6 = getFloat();
+ int i1 = getInt();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
+ }
+ break;
+ case DrawPath: {
+ SkPath* path = getPath();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
+ }
+ break;
+ case DrawLines: {
+ int count = 0;
+ float* points = getFloats(count);
+ SkPaint* paint = getPaint();
+ LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ }
+ break;
+ case DrawPoints: {
+ int count = 0;
+ float* points = getFloats(count);
+ SkPaint* paint = getPaint();
+ LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ }
+ break;
+ case DrawText: {
+ getText(&text);
+ int count = getInt();
+ float x = getFloat();
+ float y = getFloat();
+ SkPaint* paint = getPaint();
+ LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+ text.text(), text.length(), count, x, y, paint);
+ }
+ break;
+ case ResetShader: {
+ LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ }
+ break;
+ case SetupShader: {
+ SkiaShader* shader = getShader();
+ LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
+ }
+ break;
+ case ResetColorFilter: {
+ LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ }
+ break;
+ case SetupColorFilter: {
+ SkiaColorFilter *colorFilter = getColorFilter();
+ LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
+ }
+ break;
+ case ResetShadow: {
+ LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ }
+ break;
+ case SetupShadow: {
+ float radius = getFloat();
+ float dx = getFloat();
+ float dy = getFloat();
+ int color = getInt();
+ LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
+ radius, dx, dy, color);
+ }
+ break;
+ default:
+ LOGD("Display List error: op not handled: %s%s",
+ (char*) indent, OP_NAMES[op]);
+ break;
+ }
+ }
+
+ LOGD("%sDone", (char*) indent + 2);
+}
+
+/**
+ * Changes to replay(), specifically those involving opcode or parameter changes, should be mimicked
+ * in the output() function, since that function processes the same list of opcodes for the
+ * purposes of logging display list info for a given view.
+ */
bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) {
bool needsInvalidate = false;
TextContainer text;
@@ -181,9 +517,11 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level)
DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this);
#endif
+ DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
int saveCount = renderer.getSaveCount() - 1;
while (!mReader.eof()) {
int op = mReader.readInt();
+ logBuffer.writeCommand(level, op);
switch (op) {
case DrawGLFunction: {
@@ -452,6 +790,13 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level)
renderer.drawLines(points, count, getPaint());
}
break;
+ case DrawPoints: {
+ int count = 0;
+ float* points = getFloats(count);
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+ renderer.drawPoints(points, count, getPaint());
+ }
+ break;
case DrawText: {
getText(&text);
int count = getInt();
@@ -533,12 +878,6 @@ void DisplayListRenderer::reset() {
}
mBitmapResources.clear();
- for (size_t i = 0; i < mOriginalPaths.size(); i++) {
- SkPath* resource = mOriginalPaths.itemAt(i);
- caches.resourceCache.decrementRefcount(resource);
- }
- mOriginalPaths.clear();
-
for (size_t i = 0; i < mShaders.size(); i++) {
caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
}
@@ -804,8 +1143,15 @@ void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
addPaint(paint);
}
+void DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
+ addOp(DisplayList::DrawPoints);
+ addFloats(points, count);
+ addPaint(paint);
+}
+
void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
float x, float y, SkPaint* paint) {
+ if (count <= 0) return;
addOp(DisplayList::DrawText);
addText(text, bytesCount);
addInt(count);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 6fc315c..dcf2cf2 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -26,6 +26,7 @@
#include <SkTDArray.h>
#include <SkTSearch.h>
+#include "DisplayListLogBuffer.h"
#include "OpenGLRenderer.h"
#include "utils/Functor.h"
@@ -89,6 +90,7 @@ public:
DrawArc,
DrawPath,
DrawLines,
+ DrawPoints,
DrawText,
ResetShader,
SetupShader,
@@ -105,6 +107,10 @@ public:
bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
+ void output(OpenGLRenderer& renderer, uint32_t level = 0);
+
+ static void outputLogBuffer(int fd);
+
private:
void init();
@@ -193,7 +199,6 @@ private:
Vector<SkPaint*> mPaints;
Vector<SkPath*> mPaths;
- Vector<SkPath*> mOriginalPaths;
Vector<SkMatrix*> mMatrices;
Vector<SkiaShader*> mShaders;
@@ -265,6 +270,7 @@ public:
float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
void drawPath(SkPath* path, SkPaint* paint);
void drawLines(float* points, int count, SkPaint* paint);
+ void drawPoints(float* points, int count, SkPaint* paint);
void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
void resetShader();
@@ -298,10 +304,6 @@ public:
return mPaths;
}
- const Vector<SkPath*>& getOriginalPaths() const {
- return mOriginalPaths;
- }
-
const Vector<SkMatrix*>& getMatrices() const {
return mMatrices;
}
@@ -383,16 +385,9 @@ private:
SkPath* pathCopy = mPathMap.valueFor(path);
if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
- if (pathCopy == NULL) {
- pathCopy = path;
- mOriginalPaths.add(path);
- Caches& caches = Caches::getInstance();
- caches.resourceCache.incrementRefcount(path);
- } else {
- pathCopy = new SkPath(*path);
- mPaths.add(pathCopy);
- }
+ pathCopy = new SkPath(*path);
mPathMap.add(path, pathCopy);
+ mPaths.add(pathCopy);
}
addInt((int) pathCopy);
@@ -469,7 +464,6 @@ private:
Vector<SkPaint*> mPaints;
DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
- Vector<SkPath*> mOriginalPaths;
Vector<SkPath*> mPaths;
DefaultKeyedVector<SkPath*, SkPath*> mPathMap;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index aa9b40e..9bf3de8 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -35,6 +35,10 @@ namespace uirenderer {
#define DEFAULT_TEXT_CACHE_WIDTH 1024
#define DEFAULT_TEXT_CACHE_HEIGHT 256
+// We should query these values from the GL context
+#define MAX_TEXT_CACHE_WIDTH 2048
+#define MAX_TEXT_CACHE_HEIGHT 2048
+
///////////////////////////////////////////////////////////////////////////////
// Font
///////////////////////////////////////////////////////////////////////////////
@@ -55,8 +59,7 @@ Font::~Font() {
}
for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
- CachedGlyphInfo* glyph = mCachedGlyphs.valueAt(i);
- delete glyph;
+ delete mCachedGlyphs.valueAt(i);
}
}
@@ -131,48 +134,49 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
}
-Font::CachedGlyphInfo* Font::getCachedUTFChar(SkPaint* paint, int32_t utfChar) {
+Font::CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
CachedGlyphInfo* cachedGlyph = NULL;
- ssize_t index = mCachedGlyphs.indexOfKey(utfChar);
+ ssize_t index = mCachedGlyphs.indexOfKey(textUnit);
if (index >= 0) {
cachedGlyph = mCachedGlyphs.valueAt(index);
} else {
- cachedGlyph = cacheGlyph(paint, utfChar);
+ cachedGlyph = cacheGlyph(paint, textUnit);
}
// Is the glyph still in texture cache?
if (!cachedGlyph->mIsValid) {
- const SkGlyph& skiaGlyph = paint->getUnicharMetrics(utfChar);
+ const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit);
updateGlyphCache(paint, skiaGlyph, cachedGlyph);
}
return cachedGlyph;
}
-void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
- renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
+ render(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
bitmapW, bitmapH, NULL);
} else {
- renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL);
+ render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
+ 0, 0, NULL);
}
}
-void Font::measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
int numGlyphs, Rect *bounds) {
if (bounds == NULL) {
LOGE("No return rectangle provided to measure text");
return;
}
bounds->set(1e6, -1e6, -1e6, 1e6);
- renderUTF(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds);
+ render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds);
}
#define SkAutoKern_AdjustF(prev, next) (((next) - (prev) + 32) >> 6 << 16)
-void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
uint32_t bitmapW, uint32_t bitmapH,Rect *bounds) {
if (numGlyphs == 0 || text == NULL || len == 0) {
@@ -192,14 +196,14 @@ void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t
text += start;
while (glyphsLeft > 0) {
- int32_t utfChar = SkUTF16_NextUnichar((const uint16_t**) &text);
+ glyph_t glyph = GET_GLYPH(text);
// Reached the end of the string
- if (utfChar < 0) {
+ if (IS_END_OF_STRING(glyph)) {
break;
}
- CachedGlyphInfo* cachedGlyph = getCachedUTFChar(paint, utfChar);
+ CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
penX += SkAutoKern_AdjustF(prevRsbDelta, cachedGlyph->mLsbDelta);
prevRsbDelta = cachedGlyph->mRsbDelta;
@@ -265,11 +269,11 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
mState->mUploadTexture = true;
}
-Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, int32_t glyph) {
+Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) {
CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
mCachedGlyphs.add(glyph, newGlyph);
- const SkGlyph& skiaGlyph = paint->getUnicharMetrics(glyph);
+ const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph);
newGlyph->mGlyphIndex = skiaGlyph.fID;
newGlyph->mIsValid = false;
@@ -386,9 +390,17 @@ void FontRenderer::flushAllAndInvalidate() {
bool FontRenderer::cacheBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) {
// If the glyph is too tall, don't cache it
if (glyph.fHeight > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
- LOGE("Font size to large to fit in cache. width, height = %i, %i",
- (int) glyph.fWidth, (int) glyph.fHeight);
- return false;
+ if (mCacheHeight < MAX_TEXT_CACHE_HEIGHT) {
+ // Default cache not large enough for large glyphs - resize cache to
+ // max size and try again
+ flushAllAndInvalidate();
+ initTextTexture(true);
+ }
+ if (glyph.fHeight > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
+ LOGE("Font size to large to fit in cache. width, height = %i, %i",
+ (int) glyph.fWidth, (int) glyph.fHeight);
+ return false;
+ }
}
// Now copy the bitmap into the cache texture
@@ -446,16 +458,25 @@ bool FontRenderer::cacheBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint3
return true;
}
-void FontRenderer::initTextTexture() {
+void FontRenderer::initTextTexture(bool largeFonts) {
+ mCacheLines.clear();
+ if (largeFonts) {
+ mCacheWidth = MAX_TEXT_CACHE_WIDTH;
+ mCacheHeight = MAX_TEXT_CACHE_HEIGHT;
+ }
+
mTextTexture = new uint8_t[mCacheWidth * mCacheHeight];
memset(mTextTexture, 0, mCacheWidth * mCacheHeight * sizeof(uint8_t));
mUploadTexture = false;
+ if (mTextureId != 0) {
+ glDeleteTextures(1, &mTextureId);
+ }
glGenTextures(1, &mTextureId);
glBindTexture(GL_TEXTURE_2D, mTextureId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- // Initialize texture dimentions
+ // Initialize texture dimensions
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, mCacheWidth, mCacheHeight, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, 0);
@@ -480,6 +501,15 @@ void FontRenderer::initTextTexture() {
nextLine += mCacheLines.top()->mMaxHeight;
mCacheLines.push(new CacheTextureLine(mCacheWidth, 42, nextLine, 0));
nextLine += mCacheLines.top()->mMaxHeight;
+ if (largeFonts) {
+ int nextSize = 76;
+ // Make several new lines with increasing font sizes
+ while (nextSize < (int)(mCacheHeight - nextLine - (2 * nextSize))) {
+ mCacheLines.push(new CacheTextureLine(mCacheWidth, nextSize, nextLine, 0));
+ nextLine += mCacheLines.top()->mMaxHeight;
+ nextSize += 50;
+ }
+ }
mCacheLines.push(new CacheTextureLine(mCacheWidth, mCacheHeight - nextLine, nextLine, 0));
}
@@ -643,7 +673,7 @@ void FontRenderer::precacheLatin(SkPaint* paint) {
uint32_t remainingCapacity = getRemainingCacheCapacity();
uint32_t precacheIdx = 0;
while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) {
- mCurrentFont->getCachedUTFChar(paint, (int32_t) mLatinPrecache[precacheIdx]);
+ mCurrentFont->getCachedGlyph(paint, (int32_t) mLatinPrecache[precacheIdx]);
remainingCapacity = getRemainingCacheCapacity();
precacheIdx ++;
}
@@ -685,7 +715,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
}
Rect bounds;
- mCurrentFont->measureUTF(paint, text, startIndex, len, numGlyphs, &bounds);
+ mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
uint8_t* dataBuffer = new uint8_t[paddedWidth * paddedHeight];
@@ -696,7 +726,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
int penX = radius - bounds.left;
int penY = radius - bounds.bottom;
- mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, penX, penY,
+ mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
dataBuffer, paddedWidth, paddedHeight);
blurImage(dataBuffer, paddedWidth, paddedHeight, radius);
@@ -726,7 +756,7 @@ bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text
mDrawn = false;
mBounds = bounds;
mClip = clip;
- mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, x, y);
+ mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y);
mBounds = NULL;
if (mCurrentQuadIndex != 0) {
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index f685d5f..24ed6fa 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -33,8 +33,32 @@
namespace android {
namespace uirenderer {
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+#if RENDER_TEXT_AS_GLYPHS
+ typedef uint16_t glyph_t;
+ #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
+ #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
+ #define IS_END_OF_STRING(glyph) false
+#else
+ typedef SkUnichar glyph_t;
+ #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
+ #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
+ #define IS_END_OF_STRING(glyph) glyph < 0
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Declarations
+///////////////////////////////////////////////////////////////////////////////
+
class FontRenderer;
+///////////////////////////////////////////////////////////////////////////////
+// Font
+///////////////////////////////////////////////////////////////////////////////
+
/**
* Represents a font, defined by a Skia font id and a font size. A font is used
* to generate glyphs and cache them in the FontState.
@@ -51,9 +75,9 @@ public:
* Renders the specified string of text.
* If bitmap is specified, it will be used as the render target
*/
- void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
- int numGlyphs, int x, int y,
- uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
+ void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+ int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
+ uint32_t bitmapW = 0, uint32_t bitmapH = 0);
/**
* Creates a new font associated with the specified font state.
*/
@@ -69,13 +93,12 @@ protected:
MEASURE,
};
- void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
- int numGlyphs, int x, int y, RenderMode mode,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
- Rect *bounds);
+ void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+ int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
+ uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);
- void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
- int numGlyphs, Rect *bounds);
+ void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+ int numGlyphs, Rect *bounds);
struct CachedGlyphInfo {
// Has the cache been invalidated?
@@ -107,18 +130,26 @@ protected:
Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
uint32_t scaleX);
- DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
+ // Cache of glyphs
+ DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
void invalidateTextureCache();
- CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
+ CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
+ uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
- CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
+ CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
+
+ static glyph_t nextGlyph(const uint16_t** srcPtr) {
+ const uint16_t* src = *srcPtr;
+ glyph_t g = *src++;
+ *srcPtr = src;
+ return g;
+ }
FontRenderer* mState;
uint32_t mFontId;
@@ -128,6 +159,10 @@ protected:
uint32_t mScaleX;
};
+///////////////////////////////////////////////////////////////////////////////
+// Renderer
+///////////////////////////////////////////////////////////////////////////////
+
class FontRenderer {
public:
FontRenderer();
@@ -229,7 +264,7 @@ protected:
}
};
- void initTextTexture();
+ void initTextTexture(bool largeFonts = false);
bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
void flushAllAndInvalidate();
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index bb28437..0310bc3 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -45,6 +45,9 @@ struct Layer {
mesh = NULL;
meshIndices = NULL;
meshElementCount = 0;
+ isCacheable = true;
+ isTextureLayer = false;
+ renderTarget = GL_TEXTURE_2D;
}
~Layer() {
@@ -53,6 +56,23 @@ struct Layer {
}
/**
+ * Sets this layer's region to a rectangle. Computes the appropriate
+ * texture coordinates.
+ */
+ void setRegionAsRect() {
+ const android::Rect& bounds = region.getBounds();
+ regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
+ bounds.rightBottom().x, bounds.rightBottom().y);
+
+ const float texX = 1.0f / float(width);
+ const float texY = 1.0f / float(height);
+ const float height = layer.getHeight();
+ texCoords.set(
+ regionRect.left * texX, (height - regionRect.top) * texY,
+ regionRect.right * texX, (height - regionRect.bottom) * texY);
+ }
+
+ /**
* Bounds of the layer.
*/
Rect layer;
@@ -103,6 +123,11 @@ struct Layer {
* have been drawn.
*/
Region region;
+ /**
+ * If the region is a rectangle, coordinates of the
+ * region are stored here.
+ */
+ Rect regionRect;
/**
* Color filter used to draw this layer. Optional.
@@ -115,6 +140,27 @@ struct Layer {
TextureVertex* mesh;
uint16_t* meshIndices;
GLsizei meshElementCount;
+
+ /**
+ * If set to true (by default), the layer can be reused.
+ */
+ bool isCacheable;
+
+ /**
+ * When set to true, this layer must be treated as a texture
+ * layer.
+ */
+ bool isTextureLayer;
+
+ /**
+ * Optional texture coordinates transform.
+ */
+ mat4 texTransform;
+
+ /**
+ * Indicates the render target.
+ */
+ GLenum renderTarget;
}; // struct Layer
}; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index a9710ad..b2d795f 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -154,6 +154,8 @@ bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t heigh
}
bool LayerCache::put(Layer* layer) {
+ if (!layer->isCacheable) return false;
+
const uint32_t size = layer->width * layer->height * 4;
// Don't even try to cache a layer that's bigger than the cache
if (size < mMaxSize) {
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index f92e20b..f316ba7 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -20,6 +20,7 @@
#include "LayerCache.h"
#include "LayerRenderer.h"
+#include "Matrix.h"
#include "Properties.h"
#include "Rect.h"
@@ -92,11 +93,7 @@ Region* LayerRenderer::getRegion() {
void LayerRenderer::generateMesh() {
#if RENDER_LAYERS_AS_REGIONS
-#if RENDER_LAYERS_RECT_AS_RECT
if (mLayer->region.isRect() || mLayer->region.isEmpty()) {
-#else
- if (mLayer->region.isEmpty()) {
-#endif
if (mLayer->mesh) {
delete mLayer->mesh;
delete mLayer->meshIndices;
@@ -105,6 +102,8 @@ void LayerRenderer::generateMesh() {
mLayer->meshIndices = NULL;
mLayer->meshElementCount = 0;
}
+
+ mLayer->setRegionAsRect();
return;
}
@@ -167,6 +166,30 @@ void LayerRenderer::generateMesh() {
// Layers management
///////////////////////////////////////////////////////////////////////////////
+Layer* LayerRenderer::createTextureLayer() {
+ LAYER_RENDERER_LOGD("Creating new texture layer");
+
+ Layer* layer = new Layer(0, 0);
+ layer->isCacheable = false;
+ layer->isTextureLayer = true;
+ layer->blend = true;
+ layer->empty = true;
+ layer->fbo = 0;
+ layer->colorFilter = NULL;
+ layer->fbo = 0;
+ layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
+ layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
+ layer->alpha = 255;
+ layer->mode = SkXfermode::kSrcOver_Mode;
+ layer->colorFilter = NULL;
+ layer->region.clear();
+
+ glActiveTexture(GL_TEXTURE0);
+ glGenTextures(1, &layer->texture);
+
+ return layer;
+}
+
Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
@@ -246,6 +269,27 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
return true;
}
+void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
+ GLenum renderTarget, float* transform) {
+ if (layer) {
+ layer->width = width;
+ layer->height = height;
+ layer->layer.set(0.0f, 0.0f, width, height);
+ layer->region.set(width, height);
+ layer->regionRect.set(0.0f, 0.0f, width, height);
+ layer->texTransform.load(transform);
+ layer->renderTarget = renderTarget;
+
+ glBindTexture(layer->renderTarget, layer->texture);
+
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+}
+
void LayerRenderer::destroyLayer(Layer* layer) {
if (layer) {
LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index d2f565e..59cab96 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -53,8 +53,11 @@ public:
Region* getRegion();
GLint getTargetFbo();
+ static Layer* createTextureLayer();
static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
+ static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
+ GLenum renderTarget, float* transform);
static void destroyLayer(Layer* layer);
static void destroyLayerDeferred(Layer* layer);
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index e7c0fe3..9fc5131 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -67,6 +67,10 @@ bool Matrix4::isPureTranslate() {
ALMOST_EQUAL(data[kScaleX], 1.0f) && ALMOST_EQUAL(data[kScaleY], 1.0f);
}
+bool Matrix4::isSimple() {
+ return mSimpleMatrix;
+}
+
void Matrix4::load(const float* v) {
memcpy(data, v, sizeof(data));
mSimpleMatrix = false;
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 08f5d77..2fa6ab7 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -111,6 +111,7 @@ public:
}
bool isPureTranslate();
+ bool isSimple();
bool changesBounds();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d9d7d23..6c9c0eb 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -63,7 +63,7 @@ struct Blender {
// In this array, the index of each Blender equals the value of the first
// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
static const Blender gBlends[] = {
- { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO },
+ { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
{ SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
{ SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
{ SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
@@ -81,7 +81,7 @@ static const Blender gBlends[] = {
// this array's SrcOver blending mode is actually DstOver. You can refer to
// createLayer() for more information on the purpose of this array.
static const Blender gBlendsSwap[] = {
- { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO },
+ { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
{ SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
{ SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
{ SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
@@ -633,26 +633,64 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
}
}
+void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
+ float alpha = layer->alpha / 255.0f;
+
+ setupDraw();
+ if (layer->renderTarget == GL_TEXTURE_2D) {
+ setupDrawWithTexture();
+ } else {
+ setupDrawWithExternalTexture();
+ }
+ setupDrawTextureTransform();
+ setupDrawColor(alpha, alpha, alpha, alpha);
+ setupDrawColorFilter();
+ setupDrawBlending(layer->blend, layer->mode);
+ setupDrawProgram();
+ setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
+ setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms();
+ if (layer->renderTarget == GL_TEXTURE_2D) {
+ setupDrawTexture(layer->texture);
+ } else {
+ setupDrawExternalTexture(layer->texture);
+ }
+ setupDrawTextureTransformUniforms(layer->texTransform);
+ setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+
+ finishDrawTexture();
+}
+
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
- const Rect& texCoords = layer->texCoords;
- resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom);
+ if (!layer->isTextureLayer) {
+ const Rect& texCoords = layer->texCoords;
+ resetDrawTextureTexCoords(texCoords.left, texCoords.top,
+ texCoords.right, texCoords.bottom);
- drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
- layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
- &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap);
+ drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
+ layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
+ &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap);
- resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+ resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+ } else {
+ resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
+ drawTextureLayer(layer, rect);
+ resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+ }
}
void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
#if RENDER_LAYERS_AS_REGIONS
-#if RENDER_LAYERS_RECT_AS_RECT
if (layer->region.isRect()) {
- composeLayerRect(layer, rect);
+ layer->setRegionAsRect();
+
+ composeLayerRect(layer, layer->regionRect);
+
layer->region.clear();
return;
}
-#endif
if (!layer->region.isEmpty()) {
size_t count;
@@ -881,12 +919,27 @@ void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
mDescription.hasAlpha8Texture = isAlpha8;
}
+void OpenGLRenderer::setupDrawWithExternalTexture() {
+ mDescription.hasExternalTexture = true;
+}
+
+void OpenGLRenderer::setupDrawAALine() {
+ mDescription.isAA = true;
+}
+
+void OpenGLRenderer::setupDrawPoint(float pointSize) {
+ mDescription.isPoint = true;
+ mDescription.pointSize = pointSize;
+}
+
void OpenGLRenderer::setupDrawColor(int color) {
setupDrawColor(color, (color >> 24) & 0xFF);
}
void OpenGLRenderer::setupDrawColor(int color, int alpha) {
mColorA = alpha / 255.0f;
+ // Second divide of a by 255 is an optimization, allowing us to simply multiply
+ // the rgb values by a instead of also dividing by 255
const float a = mColorA / 255.0f;
mColorR = a * ((color >> 16) & 0xFF);
mColorG = a * ((color >> 8) & 0xFF);
@@ -897,6 +950,8 @@ void OpenGLRenderer::setupDrawColor(int color, int alpha) {
void OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) {
mColorA = alpha / 255.0f;
+ // Double-divide of a by 255 is an optimization, allowing us to simply multiply
+ // the rgb values by a instead of also dividing by 255
const float a = mColorA / 255.0f;
mColorR = a * ((color >> 16) & 0xFF);
mColorG = a * ((color >> 8) & 0xFF);
@@ -935,12 +990,26 @@ void OpenGLRenderer::setupDrawColorFilter() {
}
}
+void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) {
+ if (mColorSet && mode == SkXfermode::kClear_Mode) {
+ mColorA = 1.0f;
+ mColorR = mColorG = mColorB = 0.0f;
+ mSetShaderColor = mDescription.setAlpha8Color(mColorR, mColorG, mColorB, mColorA);
+ }
+}
+
void OpenGLRenderer::setupDrawBlending(SkXfermode::Mode mode, bool swapSrcDst) {
+ // When the blending mode is kClear_Mode, we need to use a modulate color
+ // argb=1,0,0,0
+ accountForClear(mode);
chooseBlending((mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode,
mDescription, swapSrcDst);
}
void OpenGLRenderer::setupDrawBlending(bool blend, SkXfermode::Mode mode, bool swapSrcDst) {
+ // When the blending mode is kClear_Mode, we need to use a modulate color
+ // argb=1,0,0,0
+ accountForClear(mode);
chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode,
mDescription, swapSrcDst);
}
@@ -965,8 +1034,8 @@ void OpenGLRenderer::setupDrawModelViewTranslate(float left, float top, float ri
}
}
-void OpenGLRenderer::setupDrawModelViewIdentity() {
- mCaches.currentProgram->set(mOrthoMatrix, mIdentity, *mSnapshot->transform);
+void OpenGLRenderer::setupDrawModelViewIdentity(bool offset) {
+ mCaches.currentProgram->set(mOrthoMatrix, mIdentity, *mSnapshot->transform, offset);
}
void OpenGLRenderer::setupDrawModelView(float left, float top, float right, float bottom,
@@ -989,6 +1058,11 @@ void OpenGLRenderer::setupDrawModelView(float left, float top, float right, floa
}
}
+void OpenGLRenderer::setupDrawPointUniforms() {
+ int slot = mCaches.currentProgram->getUniform("pointSize");
+ glUniform1f(slot, mDescription.pointSize);
+}
+
void OpenGLRenderer::setupDrawColorUniforms() {
if (mColorSet || (mShader && mSetShaderColor)) {
mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA);
@@ -1036,6 +1110,23 @@ void OpenGLRenderer::setupDrawTexture(GLuint texture) {
glEnableVertexAttribArray(mTexCoordsSlot);
}
+void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
+ bindExternalTexture(texture);
+ glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
+
+ mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
+ glEnableVertexAttribArray(mTexCoordsSlot);
+}
+
+void OpenGLRenderer::setupDrawTextureTransform() {
+ mDescription.hasTextureTransform = true;
+}
+
+void OpenGLRenderer::setupDrawTextureTransformUniforms(mat4& transform) {
+ glUniformMatrix4fv(mCaches.currentProgram->getUniform("mainTextureTransform"), 1,
+ GL_FALSE, &transform.data[0]);
+}
+
void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
if (!vertices) {
mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
@@ -1049,6 +1140,41 @@ void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint v
}
}
+void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
+ mCaches.unbindMeshBuffer();
+ glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
+ gVertexStride, vertices);
+}
+
+/**
+ * Sets up the shader to draw an AA line. We draw AA lines with quads, where there is an
+ * outer boundary that fades out to 0. The variables set in the shader define the proportion of
+ * the width and length of the primitive occupied by the AA region. The vtxWidth and vtxLength
+ * attributes (one per vertex) are values from zero to one that tells the fragment
+ * shader where the fragment is in relation to the line width/length overall; these values are
+ * then used to compute the proper color, based on whether the fragment lies in the fading AA
+ * region of the line.
+ * Note that we only pass down the width values in this setup function. The length coordinates
+ * are set up for each individual segment.
+ */
+void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords,
+ GLvoid* lengthCoords, float boundaryWidthProportion) {
+ mCaches.unbindMeshBuffer();
+ glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
+ gAAVertexStride, vertices);
+ int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
+ glEnableVertexAttribArray(widthSlot);
+ glVertexAttribPointer(widthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, widthCoords);
+ int lengthSlot = mCaches.currentProgram->getAttrib("vtxLength");
+ glEnableVertexAttribArray(lengthSlot);
+ glVertexAttribPointer(lengthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, lengthCoords);
+ int boundaryWidthSlot = mCaches.currentProgram->getUniform("boundaryWidth");
+ glUniform1f(boundaryWidthSlot, boundaryWidthProportion);
+ // Setting the inverse value saves computations per-fragment in the shader
+ int inverseBoundaryWidthSlot = mCaches.currentProgram->getUniform("inverseBoundaryWidth");
+ glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidthProportion));
+}
+
void OpenGLRenderer::finishDrawTexture() {
glDisableVertexAttribArray(mTexCoordsSlot);
}
@@ -1072,6 +1198,50 @@ bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t width, u
return false;
}
+void OpenGLRenderer::outputDisplayList(DisplayList* displayList, uint32_t level) {
+ if (displayList) {
+ displayList->output(*this, level);
+ }
+}
+
+void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint) {
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
+ setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+
+ float x = left;
+ float y = top;
+
+ bool ignoreTransform = false;
+ if (mSnapshot->transform->isPureTranslate()) {
+ x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
+ y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
+ ignoreTransform = true;
+ }
+
+ setupDraw();
+ setupDrawWithTexture(true);
+ if (paint) {
+ setupDrawAlpha8Color(paint->getColor(), alpha);
+ }
+ setupDrawColorFilter();
+ setupDrawShader();
+ setupDrawBlending(true, mode);
+ setupDrawProgram();
+ setupDrawModelView(x, y, x + texture->width, y + texture->height, ignoreTransform);
+ setupDrawTexture(texture->id);
+ setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawShaderUniforms();
+ setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+
+ finishDrawTexture();
+}
+
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
const float right = left + bitmap->width();
const float bottom = top + bitmap->height();
@@ -1085,7 +1255,11 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint
if (!texture) return;
const AutoTexture autoCleanup(texture);
- drawTextureRect(left, top, right, bottom, texture, paint);
+ if (bitmap->getConfig() == SkBitmap::kA8_Config) {
+ drawAlphaBitmap(texture, left, top, paint);
+ } else {
+ drawTextureRect(left, top, right, bottom, texture, paint);
+ }
}
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
@@ -1209,10 +1383,10 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
const float width = texture->width;
const float height = texture->height;
- const float u1 = srcLeft / width;
- const float v1 = srcTop / height;
- const float u2 = srcRight / width;
- const float v2 = srcBottom / height;
+ const float u1 = (srcLeft + 0.5f) / width;
+ const float v1 = (srcTop + 0.5f) / height;
+ const float u2 = (srcRight - 0.5f) / width;
+ const float v2 = (srcBottom - 0.5f) / height;
mCaches.unbindMeshBuffer();
resetDrawTextureTexCoords(u1, v1, u2, v2);
@@ -1297,117 +1471,375 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int
}
}
+/**
+ * This function uses a similar approach to that of AA lines in the drawLines() function.
+ * We expand the rectangle by a half pixel in screen space on all sides, and use a fragment
+ * shader to compute the translucency of the color, determined by whether a given pixel is
+ * within that boundary region and how far into the region it is.
+ */
+void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom,
+ int color, SkXfermode::Mode mode) {
+ float inverseScaleX = 1.0f;
+ float inverseScaleY = 1.0f;
+ // The quad that we use needs to account for scaling.
+ if (!mSnapshot->transform->isPureTranslate()) {
+ Matrix4 *mat = mSnapshot->transform;
+ float m00 = mat->data[Matrix4::kScaleX];
+ float m01 = mat->data[Matrix4::kSkewY];
+ float m02 = mat->data[2];
+ float m10 = mat->data[Matrix4::kSkewX];
+ float m11 = mat->data[Matrix4::kScaleX];
+ float m12 = mat->data[6];
+ float scaleX = sqrt(m00 * m00 + m01 * m01);
+ float scaleY = sqrt(m10 * m10 + m11 * m11);
+ inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0;
+ inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0;
+ }
+
+ setupDraw();
+ setupDrawAALine();
+ setupDrawColor(color);
+ setupDrawColorFilter();
+ setupDrawShader();
+ setupDrawBlending(true, mode);
+ setupDrawProgram();
+ setupDrawModelViewIdentity(true);
+ setupDrawColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawShaderIdentityUniforms();
+
+ AAVertex rects[4];
+ AAVertex* aaVertices = &rects[0];
+ void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
+ void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
+
+ float boundarySizeX = .5 * inverseScaleX;
+ float boundarySizeY = .5 * inverseScaleY;
+
+ // Adjust the rect by the AA boundary padding
+ left -= boundarySizeX;
+ right += boundarySizeX;
+ top -= boundarySizeY;
+ bottom += boundarySizeY;
+
+ float width = right - left;
+ float height = bottom - top;
+
+ float boundaryWidthProportion = (width != 0) ? (2 * boundarySizeX) / width : 0;
+ float boundaryHeightProportion = (height != 0) ? (2 * boundarySizeY) / height : 0;
+ setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, boundaryWidthProportion);
+ int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
+ int inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength");
+ glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
+ glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryHeightProportion));
+
+ if (!quickReject(left, top, right, bottom)) {
+ AAVertex::set(aaVertices++, left, bottom, 1, 1);
+ AAVertex::set(aaVertices++, left, top, 1, 0);
+ AAVertex::set(aaVertices++, right, bottom, 0, 1);
+ AAVertex::set(aaVertices++, right, top, 0, 0);
+ dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+}
+
+/**
+ * We draw lines as quads (tristrips). Using GL_LINES can be difficult because the rasterization
+ * rules for those lines produces some unexpected results, and may vary between hardware devices.
+ * The basics of lines-as-quads is easy; we simply find the normal to the line and position the
+ * corners of the quads on either side of each line endpoint, separated by the strokeWidth
+ * of the line. Hairlines are more involved because we need to account for transform scaling
+ * to end up with a one-pixel-wide line in screen space..
+ * Anti-aliased lines add another factor to the approach. We use a specialized fragment shader
+ * in combination with values that we calculate and pass down in this method. The basic approach
+ * is that the quad we create contains both the core line area plus a bounding area in which
+ * the translucent/AA pixels are drawn. The values we calculate tell the shader what
+ * proportion of the width and the length of a given segment is represented by the boundary
+ * region. The quad ends up being exactly .5 pixel larger in all directions than the non-AA quad.
+ * The bounding region is actually 1 pixel wide on all sides (half pixel on the outside, half pixel
+ * on the inside). This ends up giving the result we want, with pixels that are completely
+ * 'inside' the line area being filled opaquely and the other pixels being filled according to
+ * how far into the boundary region they are, which is determined by shader interpolation.
+ */
void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
if (mSnapshot->isIgnored()) return;
const bool isAA = paint->isAntiAlias();
- const float strokeWidth = paint->getStrokeWidth() * 0.5f;
- // A stroke width of 0 has a special meaningin Skia:
- // it draws an unscaled 1px wide line
- const bool isHairLine = paint->getStrokeWidth() == 0.0f;
-
+ // We use half the stroke width here because we're going to position the quad
+ // corner vertices half of the width away from the line endpoints
+ float halfStrokeWidth = paint->getStrokeWidth() * 0.5f;
+ // A stroke width of 0 has a special meaning in Skia:
+ // it draws a line 1 px wide regardless of current transform
+ bool isHairLine = paint->getStrokeWidth() == 0.0f;
+ float inverseScaleX = 1.0f;
+ float inverseScaleY = 1.0f;
+ bool scaled = false;
int alpha;
SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
- int verticesCount = count >> 2;
int generatedVerticesCount = 0;
- if (!isHairLine) {
- // TODO: AA needs more vertices
- verticesCount *= 6;
- } else {
- // TODO: AA will be different
- verticesCount *= 2;
+ int verticesCount = count;
+ if (count > 4) {
+ // Polyline: account for extra vertices needed for continuous tri-strip
+ verticesCount += (count - 4);
+ }
+
+ if (isHairLine || isAA) {
+ // The quad that we use for AA and hairlines needs to account for scaling. For hairlines
+ // the line on the screen should always be one pixel wide regardless of scale. For
+ // AA lines, we only want one pixel of translucent boundary around the quad.
+ if (!mSnapshot->transform->isPureTranslate()) {
+ Matrix4 *mat = mSnapshot->transform;
+ float m00 = mat->data[Matrix4::kScaleX];
+ float m01 = mat->data[Matrix4::kSkewY];
+ float m02 = mat->data[2];
+ float m10 = mat->data[Matrix4::kSkewX];
+ float m11 = mat->data[Matrix4::kScaleX];
+ float m12 = mat->data[6];
+ float scaleX = sqrt(m00*m00 + m01*m01);
+ float scaleY = sqrt(m10*m10 + m11*m11);
+ inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0;
+ inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0;
+ if (inverseScaleX != 1.0f || inverseScaleY != 1.0f) {
+ scaled = true;
+ }
+ }
}
- TextureVertex lines[verticesCount];
- TextureVertex* vertex = &lines[0];
-
+ getAlphaAndMode(paint, &alpha, &mode);
setupDraw();
+ if (isAA) {
+ setupDrawAALine();
+ }
setupDrawColor(paint->getColor(), alpha);
setupDrawColorFilter();
setupDrawShader();
- setupDrawBlending(mode);
+ if (isAA) {
+ setupDrawBlending(true, mode);
+ } else {
+ setupDrawBlending(mode);
+ }
setupDrawProgram();
- setupDrawModelViewIdentity();
+ setupDrawModelViewIdentity(true);
setupDrawColorUniforms();
setupDrawColorFilterUniforms();
setupDrawShaderIdentityUniforms();
- setupDrawMesh(vertex);
- if (!isHairLine) {
- // TODO: Handle the AA case
- for (int i = 0; i < count; i += 4) {
- // a = start point, b = end point
- vec2 a(points[i], points[i + 1]);
- vec2 b(points[i + 2], points[i + 3]);
-
- // Bias to snap to the same pixels as Skia
- a += 0.375;
- b += 0.375;
-
- // Find the normal to the line
- vec2 n = (b - a).copyNormalized() * strokeWidth;
- float x = n.x;
- n.x = -n.y;
- n.y = x;
-
- // Four corners of the rectangle defining a thick line
- vec2 p1 = a - n;
- vec2 p2 = a + n;
- vec2 p3 = b + n;
- vec2 p4 = b - n;
-
- const float left = fmin(p1.x, fmin(p2.x, fmin(p3.x, p4.x)));
- const float right = fmax(p1.x, fmax(p2.x, fmax(p3.x, p4.x)));
- const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y)));
- const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y)));
-
- if (!quickReject(left, top, right, bottom)) {
- // Draw the line as 2 triangles, could be optimized
- // by using only 4 vertices and the correct indices
- // Also we should probably used non textured vertices
- // when line AA is disabled to save on bandwidth
- TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);
-
- generatedVerticesCount += 6;
-
- dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ if (isHairLine) {
+ // Set a real stroke width to be used in quad construction
+ halfStrokeWidth = isAA? 1 : .5;
+ } else if (isAA && !scaled) {
+ // Expand boundary to enable AA calculations on the quad border
+ halfStrokeWidth += .5f;
+ }
+ Vertex lines[verticesCount];
+ Vertex* vertices = &lines[0];
+ AAVertex wLines[verticesCount];
+ AAVertex* aaVertices = &wLines[0];
+ if (!isAA) {
+ setupDrawVertices(vertices);
+ } else {
+ void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
+ void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
+ // innerProportion is the ratio of the inner (non-AA) part of the line to the total
+ // AA stroke width (the base stroke width expanded by a half pixel on either side).
+ // This value is used in the fragment shader to determine how to fill fragments.
+ // We will need to calculate the actual width proportion on each segment for
+ // scaled non-hairlines, since the boundary proportion may differ per-axis when scaled.
+ float boundaryWidthProportion = 1 / (2 * halfStrokeWidth);
+ setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, boundaryWidthProportion);
+ }
+
+ AAVertex* prevAAVertex = NULL;
+ Vertex* prevVertex = NULL;
+
+ int boundaryLengthSlot = -1;
+ int inverseBoundaryLengthSlot = -1;
+ int boundaryWidthSlot = -1;
+ int inverseBoundaryWidthSlot = -1;
+ for (int i = 0; i < count; i += 4) {
+ // a = start point, b = end point
+ vec2 a(points[i], points[i + 1]);
+ vec2 b(points[i + 2], points[i + 3]);
+ float length = 0;
+ float boundaryLengthProportion = 0;
+ float boundaryWidthProportion = 0;
+
+ // Find the normal to the line
+ vec2 n = (b - a).copyNormalized() * halfStrokeWidth;
+ if (isHairLine) {
+ if (isAA) {
+ float wideningFactor;
+ if (fabs(n.x) >= fabs(n.y)) {
+ wideningFactor = fabs(1.0f / n.x);
+ } else {
+ wideningFactor = fabs(1.0f / n.y);
+ }
+ n *= wideningFactor;
+ }
+ if (scaled) {
+ n.x *= inverseScaleX;
+ n.y *= inverseScaleY;
+ }
+ } else if (scaled) {
+ // Extend n by .5 pixel on each side, post-transform
+ vec2 extendedN = n.copyNormalized();
+ extendedN /= 2;
+ extendedN.x *= inverseScaleX;
+ extendedN.y *= inverseScaleY;
+ float extendedNLength = extendedN.length();
+ // We need to set this value on the shader prior to drawing
+ boundaryWidthProportion = extendedNLength / (halfStrokeWidth + extendedNLength);
+ n += extendedN;
+ }
+ float x = n.x;
+ n.x = -n.y;
+ n.y = x;
+
+ // aa lines expand the endpoint vertices to encompass the AA boundary
+ if (isAA) {
+ vec2 abVector = (b - a);
+ length = abVector.length();
+ abVector.normalize();
+ if (scaled) {
+ abVector.x *= inverseScaleX;
+ abVector.y *= inverseScaleY;
+ float abLength = abVector.length();
+ boundaryLengthProportion = abLength / (length + abLength);
+ } else {
+ boundaryLengthProportion = .5 / (length + 1);
}
+ abVector /= 2;
+ a -= abVector;
+ b += abVector;
}
- if (generatedVerticesCount > 0) {
- // GL_LINE does not give the result we want to match Skia
- glDrawArrays(GL_TRIANGLES, 0, generatedVerticesCount);
+ // Four corners of the rectangle defining a thick line
+ vec2 p1 = a - n;
+ vec2 p2 = a + n;
+ vec2 p3 = b + n;
+ vec2 p4 = b - n;
+
+
+ const float left = fmin(p1.x, fmin(p2.x, fmin(p3.x, p4.x)));
+ const float right = fmax(p1.x, fmax(p2.x, fmax(p3.x, p4.x)));
+ const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y)));
+ const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y)));
+
+ if (!quickReject(left, top, right, bottom)) {
+ if (!isAA) {
+ if (prevVertex != NULL) {
+ // Issue two repeat vertices to create degenerate triangles to bridge
+ // between the previous line and the new one. This is necessary because
+ // we are creating a single triangle_strip which will contain
+ // potentially discontinuous line segments.
+ Vertex::set(vertices++, prevVertex->position[0], prevVertex->position[1]);
+ Vertex::set(vertices++, p1.x, p1.y);
+ generatedVerticesCount += 2;
+ }
+ Vertex::set(vertices++, p1.x, p1.y);
+ Vertex::set(vertices++, p2.x, p2.y);
+ Vertex::set(vertices++, p4.x, p4.y);
+ Vertex::set(vertices++, p3.x, p3.y);
+ prevVertex = vertices - 1;
+ generatedVerticesCount += 4;
+ } else {
+ if (!isHairLine && scaled) {
+ // Must set width proportions per-segment for scaled non-hairlines to use the
+ // correct AA boundary dimensions
+ if (boundaryWidthSlot < 0) {
+ boundaryWidthSlot =
+ mCaches.currentProgram->getUniform("boundaryWidth");
+ inverseBoundaryWidthSlot =
+ mCaches.currentProgram->getUniform("inverseBoundaryWidth");
+ }
+ glUniform1f(boundaryWidthSlot, boundaryWidthProportion);
+ glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidthProportion));
+ }
+ if (boundaryLengthSlot < 0) {
+ boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
+ inverseBoundaryLengthSlot =
+ mCaches.currentProgram->getUniform("inverseBoundaryLength");
+ }
+ glUniform1f(boundaryLengthSlot, boundaryLengthProportion);
+ glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryLengthProportion));
+
+ if (prevAAVertex != NULL) {
+ // Issue two repeat vertices to create degenerate triangles to bridge
+ // between the previous line and the new one. This is necessary because
+ // we are creating a single triangle_strip which will contain
+ // potentially discontinuous line segments.
+ AAVertex::set(aaVertices++,prevAAVertex->position[0],
+ prevAAVertex->position[1], prevAAVertex->width, prevAAVertex->length);
+ AAVertex::set(aaVertices++, p4.x, p4.y, 1, 1);
+ generatedVerticesCount += 2;
+ }
+ AAVertex::set(aaVertices++, p4.x, p4.y, 1, 1);
+ AAVertex::set(aaVertices++, p1.x, p1.y, 1, 0);
+ AAVertex::set(aaVertices++, p3.x, p3.y, 0, 1);
+ AAVertex::set(aaVertices++, p2.x, p2.y, 0, 0);
+ prevAAVertex = aaVertices - 1;
+ generatedVerticesCount += 4;
+ }
+ dirtyLayer(a.x == b.x ? left - 1 : left, a.y == b.y ? top - 1 : top,
+ a.x == b.x ? right: right, a.y == b.y ? bottom: bottom,
+ *mSnapshot->transform);
}
- } else {
- // TODO: Handle the AA case
- for (int i = 0; i < count; i += 4) {
- const float left = fmin(points[i], points[i + 1]);
- const float right = fmax(points[i], points[i + 1]);
- const float top = fmin(points[i + 2], points[i + 3]);
- const float bottom = fmax(points[i + 2], points[i + 3]);
+ }
+ if (generatedVerticesCount > 0) {
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, generatedVerticesCount);
+ }
+}
+
+void OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
+ if (mSnapshot->isIgnored()) return;
- if (!quickReject(left, top, right, bottom)) {
- TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
- TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
+ // TODO: The paint's cap style defines whether the points are square or circular
+ // TODO: Handle AA for round points
- generatedVerticesCount += 2;
+ // A stroke width of 0 has a special meaning in Skia:
+ // it draws an unscaled 1px point
+ float strokeWidth = paint->getStrokeWidth();
+ const bool isHairLine = paint->getStrokeWidth() == 0.0f;
+ if (isHairLine) {
+ // Now that we know it's hairline, we can set the effective width, to be used later
+ strokeWidth = 1.0f;
+ }
+ const float halfWidth = strokeWidth / 2;
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
- dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
- }
- }
+ int verticesCount = count >> 1;
+ int generatedVerticesCount = 0;
- if (generatedVerticesCount > 0) {
- glLineWidth(1.0f);
- glDrawArrays(GL_LINES, 0, generatedVerticesCount);
- }
+ TextureVertex pointsData[verticesCount];
+ TextureVertex* vertex = &pointsData[0];
+
+ setupDraw();
+ setupDrawPoint(strokeWidth);
+ setupDrawColor(paint->getColor(), alpha);
+ setupDrawColorFilter();
+ setupDrawShader();
+ setupDrawBlending(mode);
+ setupDrawProgram();
+ setupDrawModelViewIdentity(true);
+ setupDrawColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawPointUniforms();
+ setupDrawShaderIdentityUniforms();
+ setupDrawMesh(vertex);
+
+ for (int i = 0; i < count; i += 2) {
+ TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
+ generatedVerticesCount++;
+ float left = points[i] - halfWidth;
+ float right = points[i] + halfWidth;
+ float top = points[i + 1] - halfWidth;
+ float bottom = points [i + 1] + halfWidth;
+ dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
}
+
+ glDrawArrays(GL_POINTS, 0, generatedVerticesCount);
}
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
@@ -1502,7 +1934,11 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
}
int color = p->getColor();
- drawColorRect(left, top, right, bottom, color, mode);
+ if (p->isAntiAlias() && !mSnapshot->transform->isSimple()) {
+ drawAARect(left, top, right, bottom, color, mode);
+ } else {
+ drawColorRect(left, top, right, bottom, color, mode);
+ }
}
void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
@@ -1512,7 +1948,16 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
}
if (mSnapshot->isIgnored()) return;
+ // TODO: We should probably make a copy of the paint instead of modifying
+ // it; modifying the paint will change its generationID the first
+ // time, which might impact caches. More investigation needed to
+ // see if it matters.
+ // If we make a copy, then drawTextDecorations() should *not* make
+ // its own copy as it does right now.
paint->setAntiAlias(true);
+#if RENDER_TEXT_AS_GLYPHS
+ paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+#endif
float length = -1.0f;
switch (paint->getTextAlign()) {
@@ -1546,27 +1991,36 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
if (mHasShadow) {
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
- const ShadowTexture* shadow = mCaches.dropShadowCache.get(paint, text, bytesCount,
- count, mShadowRadius);
+ const ShadowTexture* shadow = mCaches.dropShadowCache.get(
+ paint, text, bytesCount, count, mShadowRadius);
const AutoTexture autoCleanup(shadow);
- const float sx = x - shadow->left + mShadowDx;
- const float sy = y - shadow->top + mShadowDy;
+ const float sx = oldX - shadow->left + mShadowDx;
+ const float sy = oldY - shadow->top + mShadowDy;
const int shadowAlpha = ((mShadowColor >> 24) & 0xFF);
+ int shadowColor = mShadowColor;
+ if (mShader) {
+ shadowColor = 0xffffffff;
+ }
glActiveTexture(gTextureUnits[0]);
setupDraw();
setupDrawWithTexture(true);
- setupDrawAlpha8Color(mShadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
+ setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
+ setupDrawColorFilter();
+ setupDrawShader();
setupDrawBlending(true, mode);
setupDrawProgram();
- setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height, pureTranslate);
+ setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
setupDrawTexture(shadow->id);
setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawShaderUniforms();
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+
finishDrawTexture();
}
@@ -1658,14 +2112,9 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
#if RENDER_LAYERS_AS_REGIONS
if (!layer->region.isEmpty()) {
-#if RENDER_LAYERS_RECT_AS_RECT
if (layer->region.isRect()) {
- const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight());
- composeLayerRect(layer, r);
+ composeLayerRect(layer, layer->regionRect);
} else if (layer->mesh) {
-#else
- if (layer->mesh) {
-#endif
const float a = alpha / 255.0f;
const Rect& rect = layer->layer;
@@ -1675,13 +2124,11 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
setupDrawColorFilter();
setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
setupDrawProgram();
+ setupDrawModelViewTranslate(x, y,
+ x + layer->layer.getWidth(), y + layer->layer.getHeight());
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();
setupDrawTexture(layer->texture);
- // TODO: The current layer, if any, will be dirtied with the bounding box
- // of the layer we are drawing. Since the layer we are drawing has
- // a mesh, we know the dirty region, we should use it instead
- setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]);
glDrawElements(GL_TRIANGLES, layer->meshElementCount,
@@ -1786,14 +2233,15 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
// Handle underline and strike-through
uint32_t flags = paint->getFlags();
if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+ SkPaint paintCopy(*paint);
float underlineWidth = length;
// If length is > 0.0f, we already measured the text for the text alignment
if (length <= 0.0f) {
- underlineWidth = paint->measureText(text, bytesCount);
+ underlineWidth = paintCopy.measureText(text, bytesCount);
}
float offsetX = 0;
- switch (paint->getTextAlign()) {
+ switch (paintCopy.getTextAlign()) {
case SkPaint::kCenter_Align:
offsetX = underlineWidth * 0.5f;
break;
@@ -1805,8 +2253,7 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
}
if (underlineWidth > 0.0f) {
- const float textSize = paint->getTextSize();
- // TODO: Support stroke width < 1.0f when we have AA lines
+ const float textSize = paintCopy.getTextSize();
const float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
const float left = x - offsetX;
@@ -1836,10 +2283,9 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
points[currentPoint++] = top;
}
- SkPaint linesPaint(*paint);
- linesPaint.setStrokeWidth(strokeWidth);
+ paintCopy.setStrokeWidth(strokeWidth);
- drawLines(&points[0], pointsCount, &linesPaint);
+ drawLines(&points[0], pointsCount, &paintCopy);
}
}
}
@@ -2004,12 +2450,11 @@ void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mod
}
SkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) {
- // In the future we should look at unifying the Porter-Duff modes and
- // SkXferModes so that we can use SkXfermode::IsMode(xfer, &mode).
- if (mode == NULL) {
- return SkXfermode::kSrcOver_Mode;
+ SkXfermode::Mode resultMode;
+ if (!SkXfermode::AsMode(mode, &resultMode)) {
+ resultMode = SkXfermode::kSrcOver_Mode;
}
- return mode->fMode;
+ return resultMode;
}
void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7362473..549d6e9 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -98,6 +98,7 @@ public:
virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
Rect& dirty, uint32_t level = 0);
+ virtual void outputDisplayList(DisplayList* displayList, uint32_t level = 0);
virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
@@ -119,6 +120,7 @@ public:
float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
virtual void drawPath(SkPath* path, SkPaint* paint);
virtual void drawLines(float* points, int count, SkPaint* paint);
+ virtual void drawPoints(float* points, int count, SkPaint* paint);
virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
SkPaint* paint);
@@ -247,6 +249,8 @@ private:
*/
void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false);
+ void drawTextureLayer(Layer* layer, const Rect& rect);
+
/**
* Mark the layer as dirty at the specified coordinates. The coordinates
* are transformed with the supplied matrix.
@@ -279,6 +283,11 @@ private:
void drawShape(float left, float top, const PathTexture* texture, SkPaint* paint);
void drawRectAsShape(float left, float top, float right, float bottom, SkPaint* p);
+ void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint);
+
+ void drawAARect(float left, float top, float right, float bottom,
+ int color, SkXfermode::Mode mode);
+
/**
* Draws a textured rectangle with the specified texture. The specified coordinates
* are transformed by the current snapshot's transform matrix.
@@ -384,6 +393,14 @@ private:
}
/**
+ * Binds the specified EGLImage texture. The texture unit must have been selected
+ * prior to calling this method.
+ */
+ inline void bindExternalTexture(GLuint texture) {
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
+ }
+
+ /**
* Sets the wrap modes for the specified texture. The wrap modes are modified
* only when needed.
*/
@@ -422,6 +439,9 @@ private:
* Various methods to setup OpenGL rendering.
*/
void setupDrawWithTexture(bool isAlpha8 = false);
+ void setupDrawWithExternalTexture();
+ void setupDrawAALine();
+ void setupDrawPoint(float pointSize);
void setupDrawColor(int color);
void setupDrawColor(int color, int alpha);
void setupDrawColor(float r, float g, float b, float a);
@@ -435,11 +455,12 @@ private:
bool swapSrcDst = false);
void setupDrawProgram();
void setupDrawDirtyRegionsDisabled();
- void setupDrawModelViewIdentity();
+ void setupDrawModelViewIdentity(bool offset = false);
void setupDrawModelView(float left, float top, float right, float bottom,
bool ignoreTransform = false, bool ignoreModelView = false);
void setupDrawModelViewTranslate(float left, float top, float right, float bottom,
bool ignoreTransform = false);
+ void setupDrawPointUniforms();
void setupDrawColorUniforms();
void setupDrawPureColorUniforms();
void setupDrawShaderIdentityUniforms();
@@ -447,8 +468,15 @@ private:
void setupDrawColorFilterUniforms();
void setupDrawSimpleMesh();
void setupDrawTexture(GLuint texture);
+ void setupDrawExternalTexture(GLuint texture);
+ void setupDrawTextureTransform();
+ void setupDrawTextureTransformUniforms(mat4& transform);
void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
+ void setupDrawVertices(GLvoid* vertices);
+ void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, GLvoid* lengthCoords,
+ float strokeWidth);
void finishDrawTexture();
+ void accountForClear(SkXfermode::Mode mode);
void drawRegionRects(const Region& region);
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 11eb953..f7dacae 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -152,12 +152,12 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
float previousStepY = 0.0f;
float y1 = 0.0f;
+ float y2 = 0.0f;
float v1 = 0.0f;
for (uint32_t i = 0; i < mYCount; i++) {
float stepY = mYDivs[i];
- float y2 = 0.0f;
if (i & 1) {
const float segment = stepY - previousStepY;
y2 = y1 + floorf(segment * stretchY + 0.5f);
@@ -167,8 +167,15 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
float v2 = fmax(0.0f, stepY - 0.5f) / bitmapHeight;
if (stepY > 0.0f) {
+#if DEBUG_EXPLODE_PATCHES
+ y1 += i * EXPLODE_GAP;
+ y2 += i * EXPLODE_GAP;
+#endif
generateRow(vertex, y1, y2, v1, v2, stretchX, right - left,
bitmapWidth, quadCount);
+#if DEBUG_EXPLODE_PATCHES
+ y2 -= i * EXPLODE_GAP;
+#endif
}
y1 = y2;
@@ -178,7 +185,12 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
}
if (previousStepY != bitmapHeight) {
- generateRow(vertex, y1, bottom - top, v1, 1.0f, stretchX, right - left,
+ y2 = bottom - top;
+#if DEBUG_EXPLODE_PATCHES
+ y1 += mYCount * EXPLODE_GAP;
+ y2 += mYCount * EXPLODE_GAP;
+#endif
+ generateRow(vertex, y1, y2, v1, 1.0f, stretchX, right - left,
bitmapWidth, quadCount);
}
@@ -202,13 +214,13 @@ void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, fl
float previousStepX = 0.0f;
float x1 = 0.0f;
+ float x2 = 0.0f;
float u1 = 0.0f;
// Generate the row quad by quad
for (uint32_t i = 0; i < mXCount; i++) {
float stepX = mXDivs[i];
- float x2 = 0.0f;
if (i & 1) {
const float segment = stepX - previousStepX;
x2 = x1 + floorf(segment * stretchX + 0.5f);
@@ -218,7 +230,14 @@ void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, fl
float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth;
if (stepX > 0.0f) {
+#if DEBUG_EXPLODE_PATCHES
+ x1 += i * EXPLODE_GAP;
+ x2 += i * EXPLODE_GAP;
+#endif
generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
+#if DEBUG_EXPLODE_PATCHES
+ x2 -= i * EXPLODE_GAP;
+#endif
}
x1 = x2;
@@ -228,7 +247,12 @@ void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, fl
}
if (previousStepX != bitmapWidth) {
- generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount);
+ x2 = width;
+#if DEBUG_EXPLODE_PATCHES
+ x1 += mXCount * EXPLODE_GAP;
+ x2 += mXCount * EXPLODE_GAP;
+#endif
+ generateQuad(vertex, x1, y1, x2, y2, u1, v1, 1.0f, v2, quadCount);
}
}
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 0f0ffa2..28c9048 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -31,6 +31,12 @@ namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+#define EXPLODE_GAP 4
+
+///////////////////////////////////////////////////////////////////////////////
// 9-patch structures
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index dc67e16..7ff8b74 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -41,8 +41,7 @@ struct PathCacheEntry: public ShapeCacheEntry {
path = NULL;
}
- PathCacheEntry(const PathCacheEntry& entry):
- ShapeCacheEntry(entry) {
+ PathCacheEntry(const PathCacheEntry& entry): ShapeCacheEntry(entry) {
path = entry.path;
}
@@ -55,6 +54,7 @@ struct PathCacheEntry: public ShapeCacheEntry {
}
SkPath* path;
+
}; // PathCacheEntry
/**
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 2187f24..972dd87 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -124,8 +124,15 @@ GLuint Program::buildShader(const char* source, GLenum type) {
}
void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
- const mat4& transformMatrix) {
+ const mat4& transformMatrix, bool offset) {
mat4 t(projectionMatrix);
+ if (offset) {
+ // offset screenspace xy by an amount that compensates for typical precision issues
+ // in GPU hardware that tends to paint hor/vert lines in pixels shifted up and to the left.
+ // This offset value is based on an assumption that some hardware may use as little
+ // as 12.4 precision, so we offset by slightly more than 1/16.
+ t.translate(.375, .375, 0);
+ }
t.multiply(transformMatrix);
t.multiply(modelViewMatrix);
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index afc6f3d..764cb05 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -81,7 +81,7 @@ public:
* transform matrices.
*/
void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
- const mat4& transformMatrix);
+ const mat4& transformMatrix, bool offset = false);
/**
* Sets the color associated with this shader.
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 0b6c7b5..d419e3e 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -39,8 +39,15 @@ const char* gVS_Header_Attributes =
"attribute vec4 position;\n";
const char* gVS_Header_Attributes_TexCoords =
"attribute vec2 texCoords;\n";
+const char* gVS_Header_Attributes_AAParameters =
+ "attribute float vtxWidth;\n"
+ "attribute float vtxLength;\n";
+const char* gVS_Header_Uniforms_TextureTransform =
+ "uniform mat4 mainTextureTransform;\n";
const char* gVS_Header_Uniforms =
"uniform mat4 transform;\n";
+const char* gVS_Header_Uniforms_IsPoint =
+ "uniform mediump float pointSize;\n";
const char* gVS_Header_Uniforms_HasGradient[3] = {
// Linear
"uniform mat4 screenSpace;\n",
@@ -51,11 +58,16 @@ const char* gVS_Header_Uniforms_HasGradient[3] = {
};
const char* gVS_Header_Uniforms_HasBitmap =
"uniform mat4 textureTransform;\n"
- "uniform vec2 textureDimension;\n";
+ "uniform mediump vec2 textureDimension;\n";
const char* gVS_Header_Varyings_HasTexture =
"varying vec2 outTexCoords;\n";
+const char* gVS_Header_Varyings_IsAA =
+ "varying float widthProportion;\n"
+ "varying float lengthProportion;\n";
const char* gVS_Header_Varyings_HasBitmap =
"varying vec2 outBitmapTexCoords;\n";
+const char* gVS_Header_Varyings_PointHasBitmap =
+ "varying vec2 outPointBitmapTexCoords;\n";
const char* gVS_Header_Varyings_HasGradient[3] = {
// Linear
"varying vec2 linear;\n",
@@ -68,6 +80,8 @@ const char* gVS_Main =
"\nvoid main(void) {\n";
const char* gVS_Main_OutTexCoords =
" outTexCoords = texCoords;\n";
+const char* gVS_Main_OutTransformedTexCoords =
+ " outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
const char* gVS_Main_OutGradient[3] = {
// Linear
" linear = vec2((screenSpace * position).x, 0.5);\n",
@@ -78,8 +92,15 @@ const char* gVS_Main_OutGradient[3] = {
};
const char* gVS_Main_OutBitmapTexCoords =
" outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
+const char* gVS_Main_OutPointBitmapTexCoords =
+ " outPointBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
const char* gVS_Main_Position =
" gl_Position = transform * position;\n";
+const char* gVS_Main_PointSize =
+ " gl_PointSize = pointSize;\n";
+const char* gVS_Main_AA =
+ " widthProportion = vtxWidth;\n"
+ " lengthProportion = vtxLength;\n";
const char* gVS_Footer =
"}\n\n";
@@ -89,12 +110,24 @@ const char* gVS_Footer =
const char* gFS_Header_Extension_FramebufferFetch =
"#extension GL_NV_shader_framebuffer_fetch : enable\n\n";
+const char* gFS_Header_Extension_ExternalTexture =
+ "#extension GL_OES_EGL_image_external : require\n\n";
const char* gFS_Header =
"precision mediump float;\n\n";
const char* gFS_Uniforms_Color =
"uniform vec4 color;\n";
+const char* gFS_Uniforms_AA =
+ "uniform float boundaryWidth;\n"
+ "uniform float inverseBoundaryWidth;\n"
+ "uniform float boundaryLength;\n"
+ "uniform float inverseBoundaryLength;\n";
+const char* gFS_Header_Uniforms_PointHasBitmap =
+ "uniform vec2 textureDimension;\n"
+ "uniform float pointSize;\n";
const char* gFS_Uniforms_TextureSampler =
"uniform sampler2D sampler;\n";
+const char* gFS_Uniforms_ExternalTextureSampler =
+ "uniform samplerExternalOES sampler;\n";
const char* gFS_Uniforms_GradientSampler[3] = {
// Linear
"uniform sampler2D gradientSampler;\n",
@@ -121,6 +154,10 @@ const char* gFS_Main =
"\nvoid main(void) {\n"
" lowp vec4 fragColor;\n";
+const char* gFS_Main_PointBitmapTexCoords =
+ " vec2 outBitmapTexCoords = outPointBitmapTexCoords + "
+ "((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n";
+
// Fast cases
const char* gFS_Fast_SingleColor =
"\nvoid main(void) {\n"
@@ -154,6 +191,19 @@ const char* gFS_Fast_SingleModulateGradient =
// General case
const char* gFS_Main_FetchColor =
" fragColor = color;\n";
+const char* gFS_Main_ModulateColor =
+ " fragColor *= color.a;\n";
+const char* gFS_Main_AccountForAA =
+ " if (widthProportion < boundaryWidth) {\n"
+ " fragColor *= (widthProportion * inverseBoundaryWidth);\n"
+ " } else if (widthProportion > (1.0 - boundaryWidth)) {\n"
+ " fragColor *= ((1.0 - widthProportion) * inverseBoundaryWidth);\n"
+ " }\n"
+ " if (lengthProportion < boundaryLength) {\n"
+ " fragColor *= (lengthProportion * inverseBoundaryLength);\n"
+ " } else if (lengthProportion > (1.0 - boundaryLength)) {\n"
+ " fragColor *= ((1.0 - lengthProportion) * inverseBoundaryLength);\n"
+ " }\n";
const char* gFS_Main_FetchTexture[2] = {
// Don't modulate
" fragColor = texture2D(sampler, outTexCoords);\n",
@@ -336,38 +386,62 @@ Program* ProgramCache::generateProgram(const ProgramDescription& description, pr
String8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
// Add attributes
String8 shader(gVS_Header_Attributes);
- if (description.hasTexture) {
+ if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Attributes_TexCoords);
}
+ if (description.isAA) {
+ shader.append(gVS_Header_Attributes_AAParameters);
+ }
// Uniforms
shader.append(gVS_Header_Uniforms);
+ if (description.hasTextureTransform) {
+ shader.append(gVS_Header_Uniforms_TextureTransform);
+ }
if (description.hasGradient) {
shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]);
}
if (description.hasBitmap) {
shader.append(gVS_Header_Uniforms_HasBitmap);
}
+ if (description.isPoint) {
+ shader.append(gVS_Header_Uniforms_IsPoint);
+ }
// Varyings
- if (description.hasTexture) {
+ if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Varyings_HasTexture);
}
+ if (description.isAA) {
+ shader.append(gVS_Header_Varyings_IsAA);
+ }
if (description.hasGradient) {
shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
}
if (description.hasBitmap) {
- shader.append(gVS_Header_Varyings_HasBitmap);
+ shader.append(description.isPoint ?
+ gVS_Header_Varyings_PointHasBitmap :
+ gVS_Header_Varyings_HasBitmap);
}
// Begin the shader
shader.append(gVS_Main); {
- if (description.hasTexture) {
+ if (description.hasTextureTransform) {
+ shader.append(gVS_Main_OutTransformedTexCoords);
+ } else if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Main_OutTexCoords);
}
+ if (description.isAA) {
+ shader.append(gVS_Main_AA);
+ }
if (description.hasGradient) {
shader.append(gVS_Main_OutGradient[description.gradientType]);
}
if (description.hasBitmap) {
- shader.append(gVS_Main_OutBitmapTexCoords);
+ shader.append(description.isPoint ?
+ gVS_Main_OutPointBitmapTexCoords :
+ gVS_Main_OutBitmapTexCoords);
+ }
+ if (description.isPoint) {
+ shader.append(gVS_Main_PointSize);
}
// Output transformed position
shader.append(gVS_Main_Position);
@@ -388,23 +462,31 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (blendFramebuffer) {
shader.append(gFS_Header_Extension_FramebufferFetch);
}
+ if (description.hasExternalTexture) {
+ shader.append(gFS_Header_Extension_ExternalTexture);
+ }
shader.append(gFS_Header);
// Varyings
- if (description.hasTexture) {
+ if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Varyings_HasTexture);
}
+ if (description.isAA) {
+ shader.append(gVS_Header_Varyings_IsAA);
+ }
if (description.hasGradient) {
shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
}
if (description.hasBitmap) {
- shader.append(gVS_Header_Varyings_HasBitmap);
+ shader.append(description.isPoint ?
+ gVS_Header_Varyings_PointHasBitmap :
+ gVS_Header_Varyings_HasBitmap);
}
// Uniforms
int modulateOp = MODULATE_OP_NO_MODULATE;
- const bool singleColor = !description.hasTexture &&
+ const bool singleColor = !description.hasTexture && !description.hasExternalTexture &&
!description.hasGradient && !description.hasBitmap;
if (description.modulate || singleColor) {
@@ -413,21 +495,30 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
}
if (description.hasTexture) {
shader.append(gFS_Uniforms_TextureSampler);
+ } else if (description.hasExternalTexture) {
+ shader.append(gFS_Uniforms_ExternalTextureSampler);
+ }
+ if (description.isAA) {
+ shader.append(gFS_Uniforms_AA);
}
if (description.hasGradient) {
shader.append(gFS_Uniforms_GradientSampler[description.gradientType]);
}
+ if (description.hasBitmap && description.isPoint) {
+ shader.append(gFS_Header_Uniforms_PointHasBitmap);
+ }
// Optimization for common cases
- if (!blendFramebuffer && description.colorOp == ProgramDescription::kColorNone) {
+ if (!description.isAA && !blendFramebuffer &&
+ description.colorOp == ProgramDescription::kColorNone && !description.isPoint) {
bool fast = false;
const bool noShader = !description.hasGradient && !description.hasBitmap;
- const bool singleTexture = description.hasTexture &&
+ const bool singleTexture = (description.hasTexture || description.hasExternalTexture) &&
!description.hasAlpha8Texture && noShader;
const bool singleA8Texture = description.hasTexture &&
description.hasAlpha8Texture && noShader;
- const bool singleGradient = !description.hasTexture &&
+ const bool singleGradient = !description.hasTexture && !description.hasExternalTexture &&
description.hasGradient && !description.hasBitmap &&
description.gradientType == ProgramDescription::kGradientLinear;
@@ -490,7 +581,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
// Begin the shader
shader.append(gFS_Main); {
// Stores the result in fragColor directly
- if (description.hasTexture) {
+ if (description.hasTexture || description.hasExternalTexture) {
if (description.hasAlpha8Texture) {
if (!description.hasGradient && !description.hasBitmap) {
shader.append(gFS_Main_FetchA8Texture[modulateOp]);
@@ -503,16 +594,23 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Main_FetchColor);
}
}
+ if (description.isAA) {
+ shader.append(gFS_Main_AccountForAA);
+ }
if (description.hasGradient) {
shader.append(gFS_Main_FetchGradient[description.gradientType]);
}
if (description.hasBitmap) {
+ if (description.isPoint) {
+ shader.append(gFS_Main_PointBitmapTexCoords);
+ }
if (!description.isBitmapNpot) {
shader.append(gFS_Main_FetchBitmap);
} else {
shader.append(gFS_Main_FetchBitmapNpot);
}
}
+ bool applyModulate = false;
// Case when we have two shaders set
if (description.hasGradient && description.hasBitmap) {
int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
@@ -522,15 +620,21 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Main_BlendShadersGB);
}
shader.append(gFS_Main_BlendShaders_Modulate[op]);
+ applyModulate = true;
} else {
if (description.hasGradient) {
int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
shader.append(gFS_Main_GradientShader_Modulate[op]);
+ applyModulate = true;
} else if (description.hasBitmap) {
int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
shader.append(gFS_Main_BitmapShader_Modulate[op]);
+ applyModulate = true;
}
}
+ if (description.modulate && applyModulate) {
+ shader.append(gFS_Main_ModulateColor);
+ }
// Apply the color op if needed
shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
// Output the fragment
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index ead5b92..5c7197b 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -71,7 +71,14 @@ namespace uirenderer {
#define PROGRAM_BITMAP_WRAPT_SHIFT 11
#define PROGRAM_GRADIENT_TYPE_SHIFT 33
-#define PROGRAM_MODULATE 35
+#define PROGRAM_MODULATE_SHIFT 35
+
+#define PROGRAM_IS_POINT_SHIFT 36
+
+#define PROGRAM_HAS_AA_SHIFT 37
+
+#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
+#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
///////////////////////////////////////////////////////////////////////////////
// Types
@@ -109,6 +116,8 @@ struct ProgramDescription {
// Texturing
bool hasTexture;
bool hasAlpha8Texture;
+ bool hasExternalTexture;
+ bool hasTextureTransform;
// Modulate, this should only be set when setColor() return true
bool modulate;
@@ -117,6 +126,8 @@ struct ProgramDescription {
bool hasBitmap;
bool isBitmapNpot;
+ bool isAA;
+
bool hasGradient;
Gradient gradientType;
@@ -135,6 +146,9 @@ struct ProgramDescription {
SkXfermode::Mode framebufferMode;
bool swapSrcDst;
+ bool isPoint;
+ float pointSize;
+
/**
* Resets this description. All fields are reset back to the default
* values they hold after building a new instance.
@@ -142,6 +156,10 @@ struct ProgramDescription {
void reset() {
hasTexture = false;
hasAlpha8Texture = false;
+ hasExternalTexture = false;
+ hasTextureTransform = false;
+
+ isAA = false;
modulate = false;
@@ -162,6 +180,9 @@ struct ProgramDescription {
framebufferMode = SkXfermode::kClear_Mode;
swapSrcDst = false;
+
+ isPoint = false;
+ pointSize = 0.0f;
}
/**
@@ -223,7 +244,11 @@ struct ProgramDescription {
}
key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
- if (modulate) key |= programid(0x1) << PROGRAM_MODULATE;
+ if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
+ if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT;
+ if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
+ if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
+ if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
return key;
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 1aef99b..7c10518 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -27,8 +27,9 @@
// If turned on, layers drawn inside FBOs are optimized with regions
#define RENDER_LAYERS_AS_REGIONS 1
-// If turned on, layers that map to a single rect are drawn as a rect
-#define RENDER_LAYERS_RECT_AS_RECT 0
+
+// If turned on, text is interpreted as glyphs instead of UTF-16
+#define RENDER_TEXT_AS_GLYPHS 1
/**
* Debug level for app developers.
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index 4c626dd..b5cc29c 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -89,14 +89,17 @@ struct ShapeCacheEntry {
join = SkPaint::kDefault_Join;
cap = SkPaint::kDefault_Cap;
style = SkPaint::kFill_Style;
- miter = 4.0f;
- strokeWidth = 1.0f;
+ float v = 4.0f;
+ miter = *(uint32_t*) &v;
+ v = 1.0f;
+ strokeWidth = *(uint32_t*) &v;
+ pathEffect = NULL;
}
ShapeCacheEntry(const ShapeCacheEntry& entry):
shapeType(entry.shapeType), join(entry.join), cap(entry.cap),
style(entry.style), miter(entry.miter),
- strokeWidth(entry.strokeWidth) {
+ strokeWidth(entry.strokeWidth), pathEffect(entry.pathEffect) {
}
ShapeCacheEntry(ShapeType type, SkPaint* paint) {
@@ -108,18 +111,19 @@ struct ShapeCacheEntry {
v = paint->getStrokeWidth();
strokeWidth = *(uint32_t*) &v;
style = paint->getStyle();
+ pathEffect = paint->getPathEffect();
}
virtual ~ShapeCacheEntry() {
}
- // shapeType must be checked in subclasses operator<
ShapeType shapeType;
SkPaint::Join join;
SkPaint::Cap cap;
SkPaint::Style style;
uint32_t miter;
uint32_t strokeWidth;
+ SkPathEffect* pathEffect;
bool operator<(const ShapeCacheEntry& rhs) const {
LTE_INT(shapeType) {
@@ -128,7 +132,9 @@ struct ShapeCacheEntry {
LTE_INT(style) {
LTE_INT(miter) {
LTE_INT(strokeWidth) {
- return lessThan(rhs);
+ LTE_INT(pathEffect) {
+ return lessThan(rhs);
+ }
}
}
}
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index d46686d..28dba13 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -73,7 +73,6 @@ struct ShadowText {
text = str.string();
}
- // TODO: Should take into account fake bold and text skew
bool operator<(const ShadowText& rhs) const {
LTE_INT(len) {
LTE_INT(radius) {
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index bbf4d4a..38455dc 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -23,6 +23,18 @@ namespace uirenderer {
/**
* Simple structure to describe a vertex with a position and a texture.
*/
+struct Vertex {
+ float position[2];
+
+ static inline void set(Vertex* vertex, float x, float y) {
+ vertex[0].position[0] = x;
+ vertex[0].position[1] = y;
+ }
+}; // struct Vertex
+
+/**
+ * Simple structure to describe a vertex with a position and a texture.
+ */
struct TextureVertex {
float position[2];
float texture[2];
@@ -40,6 +52,41 @@ struct TextureVertex {
}
}; // struct TextureVertex
+/**
+ * Simple structure to describe a vertex with a position and an alpha value.
+ */
+struct AlphaVertex : Vertex {
+ float alpha;
+
+ static inline void set(AlphaVertex* vertex, float x, float y, float alpha) {
+ Vertex::set(vertex, x, y);
+ vertex[0].alpha = alpha;
+ }
+
+ static inline void setColor(AlphaVertex* vertex, float alpha) {
+ vertex[0].alpha = alpha;
+ }
+}; // struct AlphaVertex
+
+/**
+ * Simple structure to describe a vertex with a position and an alpha value.
+ */
+struct AAVertex : Vertex {
+ float width;
+ float length;
+
+ static inline void set(AAVertex* vertex, float x, float y, float width, float length) {
+ Vertex::set(vertex, x, y);
+ vertex[0].width = width;
+ vertex[0].length = length;
+ }
+
+ static inline void setColor(AAVertex* vertex, float width, float length) {
+ vertex[0].width = width;
+ vertex[0].length = length;
+ }
+}; // struct AlphaVertex
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/utils/GenerationCache.h b/libs/hwui/utils/GenerationCache.h
deleted file mode 100644
index 42e6d9b..0000000
--- a/libs/hwui/utils/GenerationCache.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2010 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_HWUI_GENERATION_CACHE_H
-#define ANDROID_HWUI_GENERATION_CACHE_H
-
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-
-namespace android {
-namespace uirenderer {
-
-template<typename EntryKey, typename EntryValue>
-class OnEntryRemoved {
-public:
- virtual ~OnEntryRemoved() { };
- virtual void operator()(EntryKey& key, EntryValue& value) = 0;
-}; // class OnEntryRemoved
-
-template<typename EntryKey, typename EntryValue>
-struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
- Entry() { }
- Entry(const Entry<EntryKey, EntryValue>& e):
- key(e.key), value(e.value), parent(e.parent), child(e.child) { }
- Entry(sp<Entry<EntryKey, EntryValue> > e):
- key(e->key), value(e->value), parent(e->parent), child(e->child) { }
-
- EntryKey key;
- EntryValue value;
-
- sp<Entry<EntryKey, EntryValue> > parent;
- sp<Entry<EntryKey, EntryValue> > child;
-}; // struct Entry
-
-template<typename K, typename V>
-class GenerationCache {
-public:
- GenerationCache(uint32_t maxCapacity);
- virtual ~GenerationCache();
-
- enum Capacity {
- kUnlimitedCapacity,
- };
-
- void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
-
- void clear();
-
- bool contains(K key) const;
- V get(K key);
- K getKeyAt(uint32_t index) const;
- bool put(K key, V value);
- V remove(K key);
- V removeOldest();
- V getValueAt(uint32_t index) const;
-
- uint32_t size() const;
-
- void addToCache(sp<Entry<K, V> > entry, K key, V value);
- void attachToCache(sp<Entry<K, V> > entry);
- void detachFromCache(sp<Entry<K, V> > entry);
-
- V removeAt(ssize_t index);
-
- KeyedVector<K, sp<Entry<K, V> > > mCache;
- uint32_t mMaxCapacity;
-
- OnEntryRemoved<K, V>* mListener;
-
- sp<Entry<K, V> > mOldest;
- sp<Entry<K, V> > mYoungest;
-}; // class GenerationCache
-
-template<typename K, typename V>
-GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) {
-};
-
-template<typename K, typename V>
-GenerationCache<K, V>::~GenerationCache() {
- clear();
-};
-
-template<typename K, typename V>
-uint32_t GenerationCache<K, V>::size() const {
- return mCache.size();
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
- mListener = listener;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::clear() {
- if (mListener) {
- for (uint32_t i = 0; i < mCache.size(); i++) {
- sp<Entry<K, V> > entry = mCache.valueAt(i);
- if (mListener) {
- (*mListener)(entry->key, entry->value);
- }
- }
- }
- mCache.clear();
- mYoungest.clear();
- mOldest.clear();
-}
-
-template<typename K, typename V>
-bool GenerationCache<K, V>::contains(K key) const {
- return mCache.indexOfKey(key) >= 0;
-}
-
-template<typename K, typename V>
-K GenerationCache<K, V>::getKeyAt(uint32_t index) const {
- return mCache.keyAt(index);
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::getValueAt(uint32_t index) const {
- return mCache.valueAt(index)->value;
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::get(K key) {
- ssize_t index = mCache.indexOfKey(key);
- if (index >= 0) {
- sp<Entry<K, V> > entry = mCache.valueAt(index);
- if (entry.get()) {
- detachFromCache(entry);
- attachToCache(entry);
- return entry->value;
- }
- }
-
- return NULL;
-}
-
-template<typename K, typename V>
-bool GenerationCache<K, V>::put(K key, V value) {
- if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
- removeOldest();
- }
-
- ssize_t index = mCache.indexOfKey(key);
- if (index < 0) {
- sp<Entry<K, V> > entry = new Entry<K, V>;
- addToCache(entry, key, value);
- return true;
- }
-
- return false;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) {
- entry->key = key;
- entry->value = value;
- mCache.add(key, entry);
- attachToCache(entry);
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::remove(K key) {
- ssize_t index = mCache.indexOfKey(key);
- if (index >= 0) {
- return removeAt(index);
- }
-
- return NULL;
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::removeAt(ssize_t index) {
- sp<Entry<K, V> > entry = mCache.valueAt(index);
- if (mListener) {
- (*mListener)(entry->key, entry->value);
- }
- mCache.removeItemsAt(index, 1);
- detachFromCache(entry);
-
- return entry->value;
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::removeOldest() {
- if (mOldest.get()) {
- ssize_t index = mCache.indexOfKey(mOldest->key);
- if (index >= 0) {
- return removeAt(index);
- }
- }
-
- return NULL;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) {
- if (!mYoungest.get()) {
- mYoungest = mOldest = entry;
- } else {
- entry->parent = mYoungest;
- mYoungest->child = entry;
- mYoungest = entry;
- }
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) {
- if (entry->parent.get()) {
- entry->parent->child = entry->child;
- }
-
- if (entry->child.get()) {
- entry->child->parent = entry->parent;
- }
-
- if (mOldest == entry) {
- mOldest = entry->child;
- }
-
- if (mYoungest == entry) {
- mYoungest = entry->parent;
- }
-
- entry->parent.clear();
- entry->child.clear();
-}
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_GENERATION_CACHE_H
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 0836887..9fabf8d 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -28,7 +28,6 @@ RSG_GENERATOR:=$(LOCAL_BUILT_MODULE)
# slangdata_output_var_name := rs_runtime_lib_bc
# LOCAL_MODULE := librslib_rt
-# LOCAL_PRELINK_MODULE := false
# LOCAL_MODULE_CLASS := STATIC_LIBRARIES
# LOCAL_MODULE_TAGS := optional
@@ -91,11 +90,15 @@ LOCAL_SRC_FILES:= \
rsContext.cpp \
rsDevice.cpp \
rsElement.cpp \
+ rsFBOCache.cpp \
+ rsFifoSocket.cpp \
rsFileA3D.cpp \
rsFont.cpp \
rsLocklessFifo.cpp \
rsObjectBase.cpp \
- rsMatrix.cpp \
+ rsMatrix2x2.cpp \
+ rsMatrix3x3.cpp \
+ rsMatrix4x4.cpp \
rsMesh.cpp \
rsMutex.cpp \
rsProgram.cpp \
@@ -107,15 +110,27 @@ LOCAL_SRC_FILES:= \
rsScript.cpp \
rsScriptC.cpp \
rsScriptC_Lib.cpp \
- rsScriptC_LibCL.cpp \
rsScriptC_LibGL.cpp \
- rsShaderCache.cpp \
rsSignal.cpp \
rsStream.cpp \
rsThreadIO.cpp \
rsType.cpp \
- rsVertexArray.cpp
-
+ driver/rsdAllocation.cpp \
+ driver/rsdBcc.cpp \
+ driver/rsdCore.cpp \
+ driver/rsdFrameBuffer.cpp \
+ driver/rsdGL.cpp \
+ driver/rsdMesh.cpp \
+ driver/rsdMeshObj.cpp \
+ driver/rsdProgram.cpp \
+ driver/rsdProgramRaster.cpp \
+ driver/rsdProgramStore.cpp \
+ driver/rsdRuntimeMath.cpp \
+ driver/rsdRuntimeStubs.cpp \
+ driver/rsdSampler.cpp \
+ driver/rsdShader.cpp \
+ driver/rsdShaderCache.cpp \
+ driver/rsdVertexArray.cpp
LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc
@@ -134,24 +149,82 @@ include $(BUILD_SHARED_LIBRARY)
# Now build a host version for serialization
include $(CLEAR_VARS)
+LOCAL_MODULE:= libRS
+LOCAL_MODULE_TAGS := optional
+
+intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,HOST,)
+
+# Generate custom headers
+
+GEN := $(addprefix $(intermediates)/, \
+ rsgApiStructs.h \
+ rsgApiFuncDecl.h \
+ )
+
+$(GEN) : PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN) : PRIVATE_CUSTOM_TOOL = $(RSG_GENERATOR) $< $@ <$(PRIVATE_PATH)/rs.spec
+$(GEN) : $(RSG_GENERATOR) $(LOCAL_PATH)/rs.spec
+$(GEN): $(intermediates)/%.h : $(LOCAL_PATH)/%.h.rsg
+ $(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+# Generate custom source files
+
+GEN := $(addprefix $(intermediates)/, \
+ rsgApi.cpp \
+ rsgApiReplay.cpp \
+ )
+
+$(GEN) : PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN) : PRIVATE_CUSTOM_TOOL = $(RSG_GENERATOR) $< $@ <$(PRIVATE_PATH)/rs.spec
+$(GEN) : $(RSG_GENERATOR) $(LOCAL_PATH)/rs.spec
+$(GEN): $(intermediates)/%.cpp : $(LOCAL_PATH)/%.cpp.rsg
+ $(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(GEN)
+
LOCAL_CFLAGS += -Werror -Wall -Wno-unused-parameter -Wno-unused-variable
LOCAL_CFLAGS += -DANDROID_RS_SERIALIZE
+LOCAL_CFLAGS += -fPIC
LOCAL_SRC_FILES:= \
+ rsAdapter.cpp \
rsAllocation.cpp \
+ rsAnimation.cpp \
rsComponent.cpp \
+ rsContext.cpp \
+ rsDevice.cpp \
rsElement.cpp \
+ rsFBOCache.cpp \
+ rsFifoSocket.cpp \
rsFileA3D.cpp \
+ rsFont.cpp \
+ rsLocklessFifo.cpp \
rsObjectBase.cpp \
+ rsMatrix2x2.cpp \
+ rsMatrix3x3.cpp \
+ rsMatrix4x4.cpp \
rsMesh.cpp \
+ rsMutex.cpp \
+ rsProgram.cpp \
+ rsProgramFragment.cpp \
+ rsProgramStore.cpp \
+ rsProgramRaster.cpp \
+ rsProgramVertex.cpp \
+ rsSampler.cpp \
+ rsScript.cpp \
+ rsScriptC.cpp \
+ rsScriptC_Lib.cpp \
+ rsScriptC_LibGL.cpp \
+ rsSignal.cpp \
rsStream.cpp \
+ rsThreadIO.cpp \
rsType.cpp
LOCAL_STATIC_LIBRARIES := libcutils libutils
LOCAL_LDLIBS := -lpthread
-LOCAL_MODULE:= libRSserialize
-LOCAL_MODULE_TAGS := optional
include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index ffa9a8c..535f713 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -24,314 +24,9 @@
extern "C" {
#endif
-//////////////////////////////////////////////////////
-//
-
-typedef void * RsAsyncVoidPtr;
-
-typedef void * RsAdapter1D;
-typedef void * RsAdapter2D;
-typedef void * RsAllocation;
-typedef void * RsAnimation;
-typedef void * RsContext;
-typedef void * RsDevice;
-typedef void * RsElement;
-typedef void * RsFile;
-typedef void * RsFont;
-typedef void * RsSampler;
-typedef void * RsScript;
-typedef void * RsMesh;
-typedef void * RsType;
-typedef void * RsObjectBase;
-
-typedef void * RsProgram;
-typedef void * RsProgramVertex;
-typedef void * RsProgramFragment;
-typedef void * RsProgramStore;
-typedef void * RsProgramRaster;
-
-typedef void (* RsBitmapCallback_t)(void *);
-
-enum RsDeviceParam {
- RS_DEVICE_PARAM_FORCE_SOFTWARE_GL,
- RS_DEVICE_PARAM_COUNT
-};
-
-typedef struct {
- uint32_t colorMin;
- uint32_t colorPref;
- uint32_t alphaMin;
- uint32_t alphaPref;
- uint32_t depthMin;
- uint32_t depthPref;
- uint32_t stencilMin;
- uint32_t stencilPref;
- uint32_t samplesMin;
- uint32_t samplesPref;
- float samplesQ;
-} RsSurfaceConfig;
-
-RsDevice rsDeviceCreate();
-void rsDeviceDestroy(RsDevice);
-void rsDeviceSetConfig(RsDevice, RsDeviceParam, int32_t value);
-
-RsContext rsContextCreate(RsDevice, uint32_t version);
-RsContext rsContextCreateGL(RsDevice, uint32_t version,
- RsSurfaceConfig sc, uint32_t dpi);
-void rsContextDestroy(RsContext);
-
-enum RsMessageToClientType {
- RS_MESSAGE_TO_CLIENT_NONE = 0,
- RS_MESSAGE_TO_CLIENT_EXCEPTION = 1,
- RS_MESSAGE_TO_CLIENT_RESIZE = 2,
- RS_MESSAGE_TO_CLIENT_ERROR = 3,
- RS_MESSAGE_TO_CLIENT_USER = 4
-};
-
-RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait);
-RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait);
-void rsContextInitToClient(RsContext);
-void rsContextDeinitToClient(RsContext);
-
-#define RS_MAX_TEXTURE 2
-#define RS_MAX_ATTRIBS 16
-
-
-enum RsAllocationUsageType {
- RS_ALLOCATION_USAGE_SCRIPT = 0x0001,
- RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE = 0x0002,
- RS_ALLOCATION_USAGE_GRAPHICS_VERTEX = 0x0004,
- RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS = 0x0008,
-
- RS_ALLOCATION_USAGE_ALL = 0x000F
-};
-
-enum RsAllocationMipmapControl {
- RS_ALLOCATION_MIPMAP_NONE = 0,
- RS_ALLOCATION_MIPMAP_FULL = 1,
- RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE = 2
-};
-
-enum RsAllocationCubemapFace {
- RS_ALLOCATION_CUBMAP_FACE_POSITVE_X = 0,
- RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_X = 1,
- RS_ALLOCATION_CUBMAP_FACE_POSITVE_Y = 2,
- RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Y = 3,
- RS_ALLOCATION_CUBMAP_FACE_POSITVE_Z = 4,
- RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Z = 5
-};
-
-enum RsDataType {
- RS_TYPE_NONE,
- RS_TYPE_FLOAT_16,
- RS_TYPE_FLOAT_32,
- RS_TYPE_FLOAT_64,
- RS_TYPE_SIGNED_8,
- RS_TYPE_SIGNED_16,
- RS_TYPE_SIGNED_32,
- RS_TYPE_SIGNED_64,
- RS_TYPE_UNSIGNED_8,
- RS_TYPE_UNSIGNED_16,
- RS_TYPE_UNSIGNED_32,
- RS_TYPE_UNSIGNED_64,
-
- RS_TYPE_BOOLEAN,
-
- RS_TYPE_UNSIGNED_5_6_5,
- RS_TYPE_UNSIGNED_5_5_5_1,
- RS_TYPE_UNSIGNED_4_4_4_4,
-
- RS_TYPE_MATRIX_4X4,
- RS_TYPE_MATRIX_3X3,
- RS_TYPE_MATRIX_2X2,
-
- RS_TYPE_ELEMENT = 1000,
- RS_TYPE_TYPE,
- RS_TYPE_ALLOCATION,
- RS_TYPE_SAMPLER,
- RS_TYPE_SCRIPT,
- RS_TYPE_MESH,
- RS_TYPE_PROGRAM_FRAGMENT,
- RS_TYPE_PROGRAM_VERTEX,
- RS_TYPE_PROGRAM_RASTER,
- RS_TYPE_PROGRAM_STORE,
-};
-
-enum RsDataKind {
- RS_KIND_USER,
-
- RS_KIND_PIXEL_L = 7,
- RS_KIND_PIXEL_A,
- RS_KIND_PIXEL_LA,
- RS_KIND_PIXEL_RGB,
- RS_KIND_PIXEL_RGBA,
-};
-
-enum RsSamplerParam {
- RS_SAMPLER_MIN_FILTER,
- RS_SAMPLER_MAG_FILTER,
- RS_SAMPLER_WRAP_S,
- RS_SAMPLER_WRAP_T,
- RS_SAMPLER_WRAP_R,
- RS_SAMPLER_ANISO
-};
-
-enum RsSamplerValue {
- RS_SAMPLER_NEAREST,
- RS_SAMPLER_LINEAR,
- RS_SAMPLER_LINEAR_MIP_LINEAR,
- RS_SAMPLER_WRAP,
- RS_SAMPLER_CLAMP,
- RS_SAMPLER_LINEAR_MIP_NEAREST,
-};
-
-enum RsTextureTarget {
- RS_TEXTURE_2D,
- RS_TEXTURE_CUBE
-};
-
-enum RsDimension {
- RS_DIMENSION_X,
- RS_DIMENSION_Y,
- RS_DIMENSION_Z,
- RS_DIMENSION_LOD,
- RS_DIMENSION_FACE,
-
- RS_DIMENSION_ARRAY_0 = 100,
- RS_DIMENSION_ARRAY_1,
- RS_DIMENSION_ARRAY_2,
- RS_DIMENSION_ARRAY_3,
- RS_DIMENSION_MAX = RS_DIMENSION_ARRAY_3
-};
-
-enum RsDepthFunc {
- RS_DEPTH_FUNC_ALWAYS,
- RS_DEPTH_FUNC_LESS,
- RS_DEPTH_FUNC_LEQUAL,
- RS_DEPTH_FUNC_GREATER,
- RS_DEPTH_FUNC_GEQUAL,
- RS_DEPTH_FUNC_EQUAL,
- RS_DEPTH_FUNC_NOTEQUAL
-};
-
-enum RsBlendSrcFunc {
- RS_BLEND_SRC_ZERO, // 0
- RS_BLEND_SRC_ONE, // 1
- RS_BLEND_SRC_DST_COLOR, // 2
- RS_BLEND_SRC_ONE_MINUS_DST_COLOR, // 3
- RS_BLEND_SRC_SRC_ALPHA, // 4
- RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, // 5
- RS_BLEND_SRC_DST_ALPHA, // 6
- RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, // 7
- RS_BLEND_SRC_SRC_ALPHA_SATURATE // 8
-};
-
-enum RsBlendDstFunc {
- RS_BLEND_DST_ZERO, // 0
- RS_BLEND_DST_ONE, // 1
- RS_BLEND_DST_SRC_COLOR, // 2
- RS_BLEND_DST_ONE_MINUS_SRC_COLOR, // 3
- RS_BLEND_DST_SRC_ALPHA, // 4
- RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, // 5
- RS_BLEND_DST_DST_ALPHA, // 6
- RS_BLEND_DST_ONE_MINUS_DST_ALPHA // 7
-};
-
-enum RsTexEnvMode {
- RS_TEX_ENV_MODE_NONE,
- RS_TEX_ENV_MODE_REPLACE,
- RS_TEX_ENV_MODE_MODULATE,
- RS_TEX_ENV_MODE_DECAL
-};
-
-enum RsProgramParam {
- RS_PROGRAM_PARAM_INPUT,
- RS_PROGRAM_PARAM_OUTPUT,
- RS_PROGRAM_PARAM_CONSTANT,
- RS_PROGRAM_PARAM_TEXTURE_TYPE,
-};
-
-enum RsPrimitive {
- RS_PRIMITIVE_POINT,
- RS_PRIMITIVE_LINE,
- RS_PRIMITIVE_LINE_STRIP,
- RS_PRIMITIVE_TRIANGLE,
- RS_PRIMITIVE_TRIANGLE_STRIP,
- RS_PRIMITIVE_TRIANGLE_FAN
-};
-
-enum RsError {
- RS_ERROR_NONE = 0,
- RS_ERROR_BAD_SHADER = 1,
- RS_ERROR_BAD_SCRIPT = 2,
- RS_ERROR_BAD_VALUE = 3,
- RS_ERROR_OUT_OF_MEMORY = 4,
- RS_ERROR_DRIVER = 5,
-
- RS_ERROR_FATAL_UNKNOWN = 0x1000,
- RS_ERROR_FATAL_DRIVER = 0x1001,
- RS_ERROR_FATAL_PROGRAM_LINK = 0x1002
-};
-
-enum RsAnimationInterpolation {
- RS_ANIMATION_INTERPOLATION_STEP,
- RS_ANIMATION_INTERPOLATION_LINEAR,
- RS_ANIMATION_INTERPOLATION_BEZIER,
- RS_ANIMATION_INTERPOLATION_CARDINAL,
- RS_ANIMATION_INTERPOLATION_HERMITE,
- RS_ANIMATION_INTERPOLATION_BSPLINE
-};
-
-enum RsAnimationEdge {
- RS_ANIMATION_EDGE_UNDEFINED,
- RS_ANIMATION_EDGE_CONSTANT,
- RS_ANIMATION_EDGE_GRADIENT,
- RS_ANIMATION_EDGE_CYCLE,
- RS_ANIMATION_EDGE_OSCILLATE,
- RS_ANIMATION_EDGE_CYLE_RELATIVE
-};
-
-enum RsA3DClassID {
- RS_A3D_CLASS_ID_UNKNOWN,
- RS_A3D_CLASS_ID_MESH,
- RS_A3D_CLASS_ID_TYPE,
- RS_A3D_CLASS_ID_ELEMENT,
- RS_A3D_CLASS_ID_ALLOCATION,
- RS_A3D_CLASS_ID_PROGRAM_VERTEX,
- RS_A3D_CLASS_ID_PROGRAM_RASTER,
- RS_A3D_CLASS_ID_PROGRAM_FRAGMENT,
- RS_A3D_CLASS_ID_PROGRAM_STORE,
- RS_A3D_CLASS_ID_SAMPLER,
- RS_A3D_CLASS_ID_ANIMATION,
- RS_A3D_CLASS_ID_ADAPTER_1D,
- RS_A3D_CLASS_ID_ADAPTER_2D,
- RS_A3D_CLASS_ID_SCRIPT_C
-};
-
-enum RsCullMode {
- RS_CULL_BACK,
- RS_CULL_FRONT,
- RS_CULL_NONE
-};
-
-typedef struct {
- RsA3DClassID classID;
- const char* objectName;
-} RsFileIndexEntry;
-
-// Script to Script
-typedef struct {
- uint32_t xStart;
- uint32_t xEnd;
- uint32_t yStart;
- uint32_t yEnd;
- uint32_t zStart;
- uint32_t zEnd;
- uint32_t arrayStart;
- uint32_t arrayEnd;
-
-} RsScriptCall;
+#include "RenderScriptDefines.h"
+//
// A3D loading and object update code.
// Should only be called at object creation, not thread safe
RsObjectBase rsaFileA3DGetEntryByIndex(RsContext, uint32_t idx, RsFile);
@@ -354,25 +49,13 @@ void rsaTypeGetNativeData(RsContext, RsType, uint32_t *typeData, uint32_t typeDa
void rsaElementGetNativeData(RsContext, RsElement, uint32_t *elemData, uint32_t elemDataSize);
void rsaElementGetSubElements(RsContext, RsElement, uint32_t *ids, const char **names, uint32_t dataSize);
-// Async commands for returning new IDS
-RsType rsaTypeCreate(RsContext, RsElement, uint32_t dimX, uint32_t dimY,
- uint32_t dimZ, bool mips, bool faces);
-RsAllocation rsaAllocationCreateTyped(RsContext rsc, RsType vtype,
- RsAllocationMipmapControl mips,
- uint32_t usages);
-RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- const void *data, uint32_t usages);
-RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- const void *data, uint32_t usages);
-#ifdef ANDROID_RS_SERIALIZE
-#define NO_RS_FUNCS
-#endif
+RsDevice rsDeviceCreate();
+void rsDeviceDestroy(RsDevice dev);
+void rsDeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value);
+RsContext rsContextCreate(RsDevice dev, uint32_t version);
+RsContext rsContextCreateGL(RsDevice dev, uint32_t version, RsSurfaceConfig sc, uint32_t dpi);
-#ifndef NO_RS_FUNCS
#include "rsgApiFuncDecl.h"
-#endif
#ifdef __cplusplus
};
diff --git a/libs/rs/RenderScriptDefines.h b/libs/rs/RenderScriptDefines.h
new file mode 100644
index 0000000..ee9645c
--- /dev/null
+++ b/libs/rs/RenderScriptDefines.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2007 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 RENDER_SCRIPT_DEFINES_H
+#define RENDER_SCRIPT_DEFINES_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//////////////////////////////////////////////////////
+//
+
+typedef void * RsAsyncVoidPtr;
+
+typedef void * RsAdapter1D;
+typedef void * RsAdapter2D;
+typedef void * RsAllocation;
+typedef void * RsAnimation;
+typedef void * RsContext;
+typedef void * RsDevice;
+typedef void * RsElement;
+typedef void * RsFile;
+typedef void * RsFont;
+typedef void * RsSampler;
+typedef void * RsScript;
+typedef void * RsMesh;
+typedef void * RsType;
+typedef void * RsObjectBase;
+
+typedef void * RsProgram;
+typedef void * RsProgramVertex;
+typedef void * RsProgramFragment;
+typedef void * RsProgramStore;
+typedef void * RsProgramRaster;
+
+typedef void * RsNativeWindow;
+
+typedef void (* RsBitmapCallback_t)(void *);
+
+typedef struct {
+ float m[16];
+} rs_matrix4x4;
+
+typedef struct {
+ float m[9];
+} rs_matrix3x3;
+
+typedef struct {
+ float m[4];
+} rs_matrix2x2;
+
+enum RsDeviceParam {
+ RS_DEVICE_PARAM_FORCE_SOFTWARE_GL,
+ RS_DEVICE_PARAM_COUNT
+};
+
+typedef struct {
+ uint32_t colorMin;
+ uint32_t colorPref;
+ uint32_t alphaMin;
+ uint32_t alphaPref;
+ uint32_t depthMin;
+ uint32_t depthPref;
+ uint32_t stencilMin;
+ uint32_t stencilPref;
+ uint32_t samplesMin;
+ uint32_t samplesPref;
+ float samplesQ;
+} RsSurfaceConfig;
+
+enum RsMessageToClientType {
+ RS_MESSAGE_TO_CLIENT_NONE = 0,
+ RS_MESSAGE_TO_CLIENT_EXCEPTION = 1,
+ RS_MESSAGE_TO_CLIENT_RESIZE = 2,
+ RS_MESSAGE_TO_CLIENT_ERROR = 3,
+ RS_MESSAGE_TO_CLIENT_USER = 4
+};
+
+enum RsAllocationUsageType {
+ RS_ALLOCATION_USAGE_SCRIPT = 0x0001,
+ RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE = 0x0002,
+ RS_ALLOCATION_USAGE_GRAPHICS_VERTEX = 0x0004,
+ RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS = 0x0008,
+ RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET = 0x0010,
+
+ RS_ALLOCATION_USAGE_ALL = 0x000F
+};
+
+enum RsAllocationMipmapControl {
+ RS_ALLOCATION_MIPMAP_NONE = 0,
+ RS_ALLOCATION_MIPMAP_FULL = 1,
+ RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE = 2
+};
+
+enum RsAllocationCubemapFace {
+ RS_ALLOCATION_CUBMAP_FACE_POSITVE_X = 0,
+ RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_X = 1,
+ RS_ALLOCATION_CUBMAP_FACE_POSITVE_Y = 2,
+ RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Y = 3,
+ RS_ALLOCATION_CUBMAP_FACE_POSITVE_Z = 4,
+ RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Z = 5
+};
+
+enum RsDataType {
+ RS_TYPE_NONE,
+ RS_TYPE_FLOAT_16,
+ RS_TYPE_FLOAT_32,
+ RS_TYPE_FLOAT_64,
+ RS_TYPE_SIGNED_8,
+ RS_TYPE_SIGNED_16,
+ RS_TYPE_SIGNED_32,
+ RS_TYPE_SIGNED_64,
+ RS_TYPE_UNSIGNED_8,
+ RS_TYPE_UNSIGNED_16,
+ RS_TYPE_UNSIGNED_32,
+ RS_TYPE_UNSIGNED_64,
+
+ RS_TYPE_BOOLEAN,
+
+ RS_TYPE_UNSIGNED_5_6_5,
+ RS_TYPE_UNSIGNED_5_5_5_1,
+ RS_TYPE_UNSIGNED_4_4_4_4,
+
+ RS_TYPE_MATRIX_4X4,
+ RS_TYPE_MATRIX_3X3,
+ RS_TYPE_MATRIX_2X2,
+
+ RS_TYPE_ELEMENT = 1000,
+ RS_TYPE_TYPE,
+ RS_TYPE_ALLOCATION,
+ RS_TYPE_SAMPLER,
+ RS_TYPE_SCRIPT,
+ RS_TYPE_MESH,
+ RS_TYPE_PROGRAM_FRAGMENT,
+ RS_TYPE_PROGRAM_VERTEX,
+ RS_TYPE_PROGRAM_RASTER,
+ RS_TYPE_PROGRAM_STORE,
+};
+
+enum RsDataKind {
+ RS_KIND_USER,
+
+ RS_KIND_PIXEL_L = 7,
+ RS_KIND_PIXEL_A,
+ RS_KIND_PIXEL_LA,
+ RS_KIND_PIXEL_RGB,
+ RS_KIND_PIXEL_RGBA,
+ RS_KIND_PIXEL_DEPTH,
+};
+
+enum RsSamplerParam {
+ RS_SAMPLER_MIN_FILTER,
+ RS_SAMPLER_MAG_FILTER,
+ RS_SAMPLER_WRAP_S,
+ RS_SAMPLER_WRAP_T,
+ RS_SAMPLER_WRAP_R,
+ RS_SAMPLER_ANISO
+};
+
+enum RsSamplerValue {
+ RS_SAMPLER_NEAREST,
+ RS_SAMPLER_LINEAR,
+ RS_SAMPLER_LINEAR_MIP_LINEAR,
+ RS_SAMPLER_WRAP,
+ RS_SAMPLER_CLAMP,
+ RS_SAMPLER_LINEAR_MIP_NEAREST,
+};
+
+enum RsTextureTarget {
+ RS_TEXTURE_2D,
+ RS_TEXTURE_CUBE
+};
+
+enum RsDimension {
+ RS_DIMENSION_X,
+ RS_DIMENSION_Y,
+ RS_DIMENSION_Z,
+ RS_DIMENSION_LOD,
+ RS_DIMENSION_FACE,
+
+ RS_DIMENSION_ARRAY_0 = 100,
+ RS_DIMENSION_ARRAY_1,
+ RS_DIMENSION_ARRAY_2,
+ RS_DIMENSION_ARRAY_3,
+ RS_DIMENSION_MAX = RS_DIMENSION_ARRAY_3
+};
+
+enum RsDepthFunc {
+ RS_DEPTH_FUNC_ALWAYS,
+ RS_DEPTH_FUNC_LESS,
+ RS_DEPTH_FUNC_LEQUAL,
+ RS_DEPTH_FUNC_GREATER,
+ RS_DEPTH_FUNC_GEQUAL,
+ RS_DEPTH_FUNC_EQUAL,
+ RS_DEPTH_FUNC_NOTEQUAL
+};
+
+enum RsBlendSrcFunc {
+ RS_BLEND_SRC_ZERO, // 0
+ RS_BLEND_SRC_ONE, // 1
+ RS_BLEND_SRC_DST_COLOR, // 2
+ RS_BLEND_SRC_ONE_MINUS_DST_COLOR, // 3
+ RS_BLEND_SRC_SRC_ALPHA, // 4
+ RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, // 5
+ RS_BLEND_SRC_DST_ALPHA, // 6
+ RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, // 7
+ RS_BLEND_SRC_SRC_ALPHA_SATURATE // 8
+};
+
+enum RsBlendDstFunc {
+ RS_BLEND_DST_ZERO, // 0
+ RS_BLEND_DST_ONE, // 1
+ RS_BLEND_DST_SRC_COLOR, // 2
+ RS_BLEND_DST_ONE_MINUS_SRC_COLOR, // 3
+ RS_BLEND_DST_SRC_ALPHA, // 4
+ RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, // 5
+ RS_BLEND_DST_DST_ALPHA, // 6
+ RS_BLEND_DST_ONE_MINUS_DST_ALPHA // 7
+};
+
+enum RsTexEnvMode {
+ RS_TEX_ENV_MODE_NONE,
+ RS_TEX_ENV_MODE_REPLACE,
+ RS_TEX_ENV_MODE_MODULATE,
+ RS_TEX_ENV_MODE_DECAL
+};
+
+enum RsProgramParam {
+ RS_PROGRAM_PARAM_INPUT,
+ RS_PROGRAM_PARAM_OUTPUT,
+ RS_PROGRAM_PARAM_CONSTANT,
+ RS_PROGRAM_PARAM_TEXTURE_TYPE,
+};
+
+enum RsPrimitive {
+ RS_PRIMITIVE_POINT,
+ RS_PRIMITIVE_LINE,
+ RS_PRIMITIVE_LINE_STRIP,
+ RS_PRIMITIVE_TRIANGLE,
+ RS_PRIMITIVE_TRIANGLE_STRIP,
+ RS_PRIMITIVE_TRIANGLE_FAN
+};
+
+enum RsError {
+ RS_ERROR_NONE = 0,
+ RS_ERROR_BAD_SHADER = 1,
+ RS_ERROR_BAD_SCRIPT = 2,
+ RS_ERROR_BAD_VALUE = 3,
+ RS_ERROR_OUT_OF_MEMORY = 4,
+ RS_ERROR_DRIVER = 5,
+
+ RS_ERROR_FATAL_UNKNOWN = 0x1000,
+ RS_ERROR_FATAL_DRIVER = 0x1001,
+ RS_ERROR_FATAL_PROGRAM_LINK = 0x1002
+};
+
+enum RsAnimationInterpolation {
+ RS_ANIMATION_INTERPOLATION_STEP,
+ RS_ANIMATION_INTERPOLATION_LINEAR,
+ RS_ANIMATION_INTERPOLATION_BEZIER,
+ RS_ANIMATION_INTERPOLATION_CARDINAL,
+ RS_ANIMATION_INTERPOLATION_HERMITE,
+ RS_ANIMATION_INTERPOLATION_BSPLINE
+};
+
+enum RsAnimationEdge {
+ RS_ANIMATION_EDGE_UNDEFINED,
+ RS_ANIMATION_EDGE_CONSTANT,
+ RS_ANIMATION_EDGE_GRADIENT,
+ RS_ANIMATION_EDGE_CYCLE,
+ RS_ANIMATION_EDGE_OSCILLATE,
+ RS_ANIMATION_EDGE_CYLE_RELATIVE
+};
+
+enum RsA3DClassID {
+ RS_A3D_CLASS_ID_UNKNOWN,
+ RS_A3D_CLASS_ID_MESH,
+ RS_A3D_CLASS_ID_TYPE,
+ RS_A3D_CLASS_ID_ELEMENT,
+ RS_A3D_CLASS_ID_ALLOCATION,
+ RS_A3D_CLASS_ID_PROGRAM_VERTEX,
+ RS_A3D_CLASS_ID_PROGRAM_RASTER,
+ RS_A3D_CLASS_ID_PROGRAM_FRAGMENT,
+ RS_A3D_CLASS_ID_PROGRAM_STORE,
+ RS_A3D_CLASS_ID_SAMPLER,
+ RS_A3D_CLASS_ID_ANIMATION,
+ RS_A3D_CLASS_ID_ADAPTER_1D,
+ RS_A3D_CLASS_ID_ADAPTER_2D,
+ RS_A3D_CLASS_ID_SCRIPT_C
+};
+
+enum RsCullMode {
+ RS_CULL_BACK,
+ RS_CULL_FRONT,
+ RS_CULL_NONE
+};
+
+typedef struct {
+ RsA3DClassID classID;
+ const char* objectName;
+} RsFileIndexEntry;
+
+// Script to Script
+typedef struct {
+ uint32_t xStart;
+ uint32_t xEnd;
+ uint32_t yStart;
+ uint32_t yEnd;
+ uint32_t zStart;
+ uint32_t zEnd;
+ uint32_t arrayStart;
+ uint32_t arrayEnd;
+
+} RsScriptCall;
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // RENDER_SCRIPT_DEFINES_H
+
+
+
+
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/rsScriptC_LibCL.cpp b/libs/rs/driver/rsdRuntimeMath.cpp
index 8a0aa47..acb990d 100644
--- a/libs/rs/rsScriptC_LibCL.cpp
+++ b/libs/rs/driver/rsdRuntimeMath.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -16,8 +16,12 @@
#include "rsContext.h"
#include "rsScriptC.h"
+#include "rsMatrix4x4.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix2x2.h"
-// Implements rs_cl.rsh
+#include "rsdCore.h"
+#include "rsdRuntime.h"
using namespace android;
@@ -135,6 +139,135 @@ static float SC_sign_f32(float value) {
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
//////////////////////////////////////////////////////////////////////////////
@@ -156,8 +289,7 @@ static float SC_sign_f32(float value) {
// ::= f # float
// ::= d # double
-static ScriptCState::SymbolTable_t gSyms[] = {
- // OpenCL math
+static RsdSymbolTable gSyms[] = {
{ "_Z4acosf", (void *)&acosf, true },
{ "_Z5acoshf", (void *)&acoshf, true },
{ "_Z4asinf", (void *)&asinf, true },
@@ -215,7 +347,6 @@ static ScriptCState::SymbolTable_t gSyms[] = {
{ "_Z6tgammaf", (void *)&tgammaf, true },
{ "_Z5truncf", (void *)&truncf, true },
- // OpenCL Int
{ "_Z3absi", (void *)&SC_abs_i32, true },
{ "_Z3abss", (void *)&SC_abs_i16, true },
{ "_Z3absc", (void *)&SC_abs_i8, true },
@@ -238,7 +369,6 @@ static ScriptCState::SymbolTable_t gSyms[] = {
{ "_Z3minss", (void *)&SC_min_i16, true },
{ "_Z3mincc", (void *)&SC_min_i8, true },
- // OpenCL 6.11.4
{ "_Z5clampfff", (void *)&SC_clamp_f32, true },
{ "_Z7degreesf", (void *)&SC_degrees, true },
{ "_Z3maxff", (void *)&SC_max_f32, true },
@@ -249,11 +379,57 @@ static ScriptCState::SymbolTable_t gSyms[] = {
//{ "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 ScriptCState::SymbolTable_t * ScriptCState::lookupSymbolCL(const char *sym) {
- ScriptCState::SymbolTable_t *syms = gSyms;
+const RsdSymbolTable * rsdLookupSymbolMath(const char *sym) {
+ const RsdSymbolTable *syms = gSyms;
while (syms->mPtr) {
if (!strcmp(syms->mName, sym)) {
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/rsShaderCache.cpp b/libs/rs/driver/rsdShaderCache.cpp
index e8d89c2..d11490c 100644
--- a/libs/rs/rsShaderCache.cpp
+++ b/libs/rs/driver/rsdShaderCache.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,25 +14,31 @@
* limitations under the License.
*/
-#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
+#include <rs_hal.h>
+#include <rsContext.h>
+
+#include "rsdShader.h"
+#include "rsdShaderCache.h"
+#include "rsdGL.h"
+
#include <GLES/gl.h>
#include <GLES2/gl2.h>
-#endif //ANDROID_RS_SERIALIZE
using namespace android;
using namespace android::renderscript;
-ShaderCache::ShaderCache() {
+RsdShaderCache::RsdShaderCache() {
mEntries.setCapacity(16);
+ mVertexDirty = true;
+ mFragmentDirty = true;
}
-ShaderCache::~ShaderCache() {
+RsdShaderCache::~RsdShaderCache() {
cleanupAll();
}
-void ShaderCache::updateUniformArrayData(Context *rsc, Program *prog, uint32_t linkedID,
+void RsdShaderCache::updateUniformArrayData(const Context *rsc, RsdShader *prog, uint32_t linkedID,
UniformData *data, const char* logTag,
UniformQueryData **uniformList, uint32_t uniListSize) {
@@ -54,14 +60,14 @@ void ShaderCache::updateUniformArrayData(Context *rsc, Program *prog, uint32_t l
}
}
-void ShaderCache::populateUniformData(Program *prog, uint32_t linkedID, UniformData *data) {
+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 ShaderCache::hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag) {
+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) {
@@ -77,7 +83,31 @@ bool ShaderCache::hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag) {
return false;
}
-bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag) {
+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);
}
@@ -89,7 +119,7 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
if (!vtx->getShaderID() || !frag->getShaderID()) {
return false;
}
- //LOGV("ShaderCache lookup vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID());
+ //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()) &&
@@ -98,13 +128,13 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
//LOGV("SC using program %i", mEntries[ct]->program);
glUseProgram(mEntries[ct]->program);
mCurrent = mEntries[ct];
- //LOGV("ShaderCache hit, using %i", ct);
- rsc->checkError("ShaderCache::lookup (hit)");
+ //LOGV("RsdShaderCache hit, using %i", ct);
+ rsdGLCheckError(rsc, "RsdShaderCache::link (hit)");
return true;
}
}
- //LOGV("ShaderCache miss");
+ //LOGV("RsdShaderCache miss");
//LOGE("e0 %x", glGetError());
ProgramEntry *e = new ProgramEntry(vtx->getAttribCount(),
vtx->getUniformCount(),
@@ -120,12 +150,10 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
//LOGE("e1 %x", glGetError());
glAttachShader(pgm, frag->getShaderID());
- if (!vtx->isUserProgram()) {
- glBindAttribLocation(pgm, 0, "ATTRIB_position");
- glBindAttribLocation(pgm, 1, "ATTRIB_color");
- glBindAttribLocation(pgm, 2, "ATTRIB_normal");
- glBindAttribLocation(pgm, 3, "ATTRIB_texture0");
- }
+ 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);
@@ -203,11 +231,12 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
//LOGV("SC made program %i", e->program);
glUseProgram(e->program);
- rsc->checkError("ShaderCache::lookup (miss)");
+ rsdGLCheckError(rsc, "RsdShaderCache::link (miss)");
+
return true;
}
-int32_t ShaderCache::vtxAttribSlot(const String8 &attrName) const {
+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;
@@ -216,7 +245,7 @@ int32_t ShaderCache::vtxAttribSlot(const String8 &attrName) const {
return -1;
}
-void ShaderCache::cleanupVertex(uint32_t id) {
+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) {
@@ -230,7 +259,7 @@ void ShaderCache::cleanupVertex(uint32_t id) {
}
}
-void ShaderCache::cleanupFragment(uint32_t id) {
+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) {
@@ -244,7 +273,7 @@ void ShaderCache::cleanupFragment(uint32_t id) {
}
}
-void ShaderCache::cleanupAll() {
+void RsdShaderCache::cleanupAll() {
for (uint32_t ct=0; ct < mEntries.size(); ct++) {
glDeleteProgram(mEntries[ct]->program);
free(mEntries[ct]);
diff --git a/libs/rs/rsShaderCache.h b/libs/rs/driver/rsdShaderCache.h
index 3540366..17ee3e8 100644
--- a/libs/rs/rsShaderCache.h
+++ b/libs/rs/driver/rsdShaderCache.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,38 +14,59 @@
* limitations under the License.
*/
-#ifndef ANDROID_SHADER_CACHE_H
-#define ANDROID_SHADER_CACHE_H
+#ifndef ANDROID_RSD_SHADER_CACHE_H
+#define ANDROID_RSD_SHADER_CACHE_H
-
-#include "rsObjectBase.h"
-#include "rsVertexArray.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 ShaderCache {
+class RsdShaderCache {
public:
- ShaderCache();
- virtual ~ShaderCache();
+ RsdShaderCache();
+ virtual ~RsdShaderCache();
+
+ void setActiveVertex(RsdShader *pv) {
+ mVertexDirty = true;
+ mVertex = pv;
+ }
- bool lookup(Context *rsc, ProgramVertex *, ProgramFragment *);
+ 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 String8 &attrName) const;
+ 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;
@@ -111,21 +132,19 @@ protected:
UniformData *vtxUniforms;
UniformData *fragUniforms;
};
- Vector<ProgramEntry*> mEntries;
+ android::Vector<ProgramEntry*> mEntries;
ProgramEntry *mCurrent;
- bool hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag);
- void populateUniformData(Program *prog, uint32_t linkedID, UniformData *data);
- void updateUniformArrayData(Context *rsc, Program *prog, uint32_t linkedID,
+ 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_SHADER_CACHE_H
+#endif //ANDROID_RSD_SHADER_CACHE_H
diff --git a/libs/rs/rsVertexArray.cpp b/libs/rs/driver/rsdVertexArray.cpp
index 354ee89..62ec107 100644
--- a/libs/rs/rsVertexArray.cpp
+++ b/libs/rs/driver/rsdVertexArray.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,28 +14,33 @@
* limitations under the License.
*/
-#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
+#include <rs_hal.h>
+#include <rsContext.h>
+
#include <GLES/gl.h>
#include <GLES2/gl2.h>
-#endif
+
+#include "rsdGL.h"
+#include "rsdCore.h"
+#include "rsdVertexArray.h"
+#include "rsdShaderCache.h"
using namespace android;
using namespace android::renderscript;
-VertexArray::VertexArray(const Attrib *attribs, uint32_t numAttribs) {
+RsdVertexArray::RsdVertexArray(const Attrib *attribs, uint32_t numAttribs) {
mAttribs = attribs;
mCount = numAttribs;
}
-VertexArray::~VertexArray() {
+RsdVertexArray::~RsdVertexArray() {
}
-VertexArray::Attrib::Attrib() {
+RsdVertexArray::Attrib::Attrib() {
clear();
}
-void VertexArray::Attrib::clear() {
+void RsdVertexArray::Attrib::clear() {
buffer = 0;
offset = 0;
type = 0;
@@ -46,7 +51,7 @@ void VertexArray::Attrib::clear() {
name.setTo("");
}
-void VertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride,
+void RsdVertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride,
bool normalized, uint32_t offset,
const char *name) {
clear();
@@ -58,7 +63,7 @@ void VertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride,
this->name.setTo(name);
}
-void VertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
+void RsdVertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
if (idx == 0) {
LOGV("Starting vertex attribute binding");
}
@@ -74,11 +79,15 @@ void VertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
mAttribs[idx].offset);
}
-void VertexArray::setupGL2(const Context *rsc,
- class VertexArrayState *state,
- ShaderCache *sc) const {
- rsc->checkError("VertexArray::setupGL2 start");
+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);
@@ -86,7 +95,7 @@ void VertexArray::setupGL2(const Context *rsc,
}
}
- rsc->checkError("VertexArray::setupGL2 disabled");
+ 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) {
@@ -105,22 +114,22 @@ void VertexArray::setupGL2(const Context *rsc,
mAttribs[ct].stride,
mAttribs[ct].ptr + mAttribs[ct].offset);
}
- rsc->checkError("VertexArray::setupGL2 done");
+ rsdGLCheckError(rsc, "RsdVertexArray::setup done");
}
////////////////////////////////////////////
-VertexArrayState::VertexArrayState() {
+RsdVertexArrayState::RsdVertexArrayState() {
mAttrsEnabled = NULL;
mAttrsEnabledSize = 0;
}
-VertexArrayState::~VertexArrayState() {
+RsdVertexArrayState::~RsdVertexArrayState() {
if (mAttrsEnabled) {
delete[] mAttrsEnabled;
mAttrsEnabled = NULL;
}
}
-void VertexArrayState::init(Context *rsc) {
- mAttrsEnabledSize = rsc->getMaxVertexAttributes();
+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/rsVertexArray.h b/libs/rs/driver/rsdVertexArray.h
index 45d9e82..3e807a3 100644
--- a/libs/rs/rsVertexArray.h
+++ b/libs/rs/driver/rsdVertexArray.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,20 +14,21 @@
* limitations under the License.
*/
-#ifndef ANDROID_VERTEX_ARRAY_H
-#define ANDROID_VERTEX_ARRAY_H
+#ifndef ANDROID_RSD_VERTEX_ARRAY_H
+#define ANDROID_RSD_VERTEX_ARRAY_H
-
-#include "rsObjectBase.h"
-
-// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
-class ShaderCache;
+class Context;
+
+}
+}
+
+#include <utils/String8.h>
// An element is a group of Components that occupies one cell in a structure.
-class VertexArray {
+class RsdVertexArray {
public:
class Attrib {
public:
@@ -38,17 +39,17 @@ public:
uint32_t size;
uint32_t stride;
bool normalized;
- String8 name;
+ 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);
};
- VertexArray(const Attrib *attribs, uint32_t numAttribs);
- virtual ~VertexArray();
+ RsdVertexArray(const Attrib *attribs, uint32_t numAttribs);
+ virtual ~RsdVertexArray();
- void setupGL2(const Context *rsc, class VertexArrayState *, ShaderCache *) const;
+ void setup(const android::renderscript::Context *rsc) const;
void logAttrib(uint32_t idx, uint32_t slot) const;
protected:
@@ -61,20 +62,18 @@ protected:
};
-class VertexArrayState {
+class RsdVertexArrayState {
public:
- VertexArrayState();
- ~VertexArrayState();
- void init(Context *);
+ RsdVertexArrayState();
+ ~RsdVertexArrayState();
+ void init(uint32_t maxAttrs);
bool *mAttrsEnabled;
uint32_t mAttrsEnabledSize;
};
-}
-}
-#endif //ANDROID_VERTEX_ARRAY_H
+#endif //ANDROID_RSD_VERTEX_ARRAY_H
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 7e23cec..87d764d 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -1,6 +1,72 @@
+ContextDestroy {
+ direct
+}
+
+ContextGetMessage {
+ direct
+ param void *data
+ param size_t *receiveLen
+ param uint32_t *usrID
+ ret RsMessageToClientType
+}
+
+ContextPeekMessage {
+ direct
+ param size_t *receiveLen
+ param uint32_t *usrID
+ ret RsMessageToClientType
+}
+
+ContextInitToClient {
+ direct
+}
+
+ContextDeinitToClient {
+ direct
+}
+
+TypeCreate {
+ direct
+ param RsElement e
+ param uint32_t dimX
+ param uint32_t dimY
+ param uint32_t dimZ
+ param bool mips
+ param bool faces
+ ret RsType
+}
+
+AllocationCreateTyped {
+ direct
+ param RsType vtype
+ param RsAllocationMipmapControl mips
+ param uint32_t usages
+ ret RsAllocation
+}
+
+AllocationCreateFromBitmap {
+ direct
+ param RsType vtype
+ param RsAllocationMipmapControl mips
+ param const void *data
+ param uint32_t usages
+ ret RsAllocation
+}
+
+AllocationCubeCreateFromBitmap {
+ direct
+ param RsType vtype
+ param RsAllocationMipmapControl mips
+ param const void *data
+ param uint32_t usages
+ ret RsAllocation
+}
+
+
+
ContextFinish {
- handcodeApi
+ sync
}
ContextBindRootScript {
@@ -36,7 +102,7 @@ ContextResume {
ContextSetSurface {
param uint32_t width
param uint32_t height
- param ANativeWindow *sur
+ param RsNativeWindow sur
}
ContextDump {
@@ -51,9 +117,8 @@ ContextDestroyWorker {
}
AssignName {
- param void *obj
+ param RsObjectBase obj
param const char *name
- param size_t len
}
ObjDestroy {
@@ -69,10 +134,8 @@ ElementCreate {
}
ElementCreate2 {
- param size_t count
param const RsElement * elements
param const char ** names
- param const size_t * nameLengths
param const uint32_t * arraySize
ret RsElement
}
@@ -80,7 +143,6 @@ ElementCreate2 {
AllocationCopyToBitmap {
param RsAllocation alloc
param void * data
- param size_t dataLen
}
@@ -90,9 +152,6 @@ Allocation1DData {
param uint32_t lod
param uint32_t count
param const void *data
- param uint32_t bytes
- handcodeApi
- togglePlay
}
Allocation1DElementData {
@@ -101,9 +160,6 @@ Allocation1DElementData {
param uint32_t lod
param const void *data
param uint32_t comp_offset
- param uint32_t bytes
- handcodeApi
- togglePlay
}
Allocation2DData {
@@ -115,7 +171,6 @@ Allocation2DData {
param uint32_t w
param uint32_t h
param const void *data
- param uint32_t bytes
}
Allocation2DElementData {
@@ -126,7 +181,6 @@ Allocation2DElementData {
param RsAllocationCubemapFace face
param const void *data
param uint32_t element_offset
- param uint32_t bytes
}
AllocationGenerateMipmaps {
@@ -155,24 +209,15 @@ AllocationResize2D {
param uint32_t dimY
}
-SamplerBegin {
- }
-
-SamplerSet {
- param RsSamplerParam p
- param RsSamplerValue value
- }
-
-SamplerSet2 {
- param RsSamplerParam p
- param float value
- }
-
SamplerCreate {
- ret RsSampler
- }
-
-
+ param RsSamplerValue magFilter
+ param RsSamplerValue minFilter
+ param RsSamplerValue wrapS
+ param RsSamplerValue wrapT
+ param RsSamplerValue wrapR
+ param float mAniso
+ ret RsSampler
+}
ScriptBindAllocation {
param RsScript vtm
@@ -180,18 +225,11 @@ ScriptBindAllocation {
param uint32_t slot
}
-
-ScriptCBegin {
- }
-
-
ScriptSetTimeZone {
param RsScript s
param const char * timeZone
- param uint32_t length
}
-
ScriptInvoke {
param RsScript s
param uint32_t slot
@@ -201,11 +239,16 @@ ScriptInvokeV {
param RsScript s
param uint32_t slot
param const void * data
- param uint32_t dataLen
- handcodeApi
- togglePlay
}
+ScriptForEach {
+ param RsScript s
+ param uint32_t slot
+ param RsAllocation ain
+ param RsAllocation aout
+ param const void * usr
+}
+
ScriptSetVarI {
param RsScript s
param uint32_t slot
@@ -240,55 +283,27 @@ ScriptSetVarV {
param RsScript s
param uint32_t slot
param const void * data
- param uint32_t dataLen
- handcodeApi
- togglePlay
}
-ScriptCSetText {
- param const char * text
- param uint32_t length
- }
-
ScriptCCreate {
- param const char * packageName
param const char * resName
param const char * cacheDir
+ param const char * text
ret RsScript
}
-ProgramStoreBegin {
- param RsElement in
- param RsElement out
- }
-
-ProgramStoreColorMask {
- param bool r
- param bool g
- param bool b
- param bool a
- }
-
-ProgramStoreBlendFunc {
+ProgramStoreCreate {
+ param bool colorMaskR
+ param bool colorMaskG
+ param bool colorMaskB
+ param bool colorMaskA
+ param bool depthMask
+ param bool ditherEnable
param RsBlendSrcFunc srcFunc
param RsBlendDstFunc destFunc
- }
-
-ProgramStoreDepthMask {
- param bool enable
-}
-
-ProgramStoreDither {
- param bool enable
-}
-
-ProgramStoreDepthFunc {
- param RsDepthFunc func
-}
-
-ProgramStoreCreate {
+ param RsDepthFunc depthFunc
ret RsProgramStore
}
@@ -296,19 +311,11 @@ ProgramRasterCreate {
param bool pointSmooth
param bool lineSmooth
param bool pointSprite
+ param float lineWidth
+ param RsCullMode cull
ret RsProgramRaster
}
-ProgramRasterSetLineWidth {
- param RsProgramRaster pr
- param float lw
-}
-
-ProgramRasterSetCullMode {
- param RsProgramRaster pr
- param RsCullMode mode
-}
-
ProgramBindConstants {
param RsProgram vp
param uint32_t slot
@@ -330,17 +337,13 @@ ProgramBindSampler {
ProgramFragmentCreate {
param const char * shaderText
- param uint32_t shaderLength
param const uint32_t * params
- param uint32_t paramLength
ret RsProgramFragment
}
ProgramVertexCreate {
param const char * shaderText
- param uint32_t shaderLength
param const uint32_t * params
- param uint32_t paramLength
ret RsProgramVertex
}
@@ -355,41 +358,13 @@ FontCreateFromMemory {
param const char *name
param float fontSize
param uint32_t dpi
- param const void *data
- param uint32_t dataLen
+ param const void *data
ret RsFont
}
MeshCreate {
+ param RsAllocation *vtx
+ param RsAllocation *idx
+ param uint32_t *primType
ret RsMesh
- param uint32_t vtxCount
- param uint32_t idxCount
- }
-
-MeshBindIndex {
- param RsMesh mesh
- param RsAllocation idx
- param uint32_t primType
- param uint32_t slot
}
-
-MeshBindVertex {
- param RsMesh mesh
- param RsAllocation vtx
- param uint32_t slot
- }
-
-MeshInitVertexAttribs {
- param RsMesh mesh
- }
-
-AnimationCreate {
- param const float *inValues
- param const float *outValues
- param uint32_t valueCount
- param RsAnimationInterpolation interp
- param RsAnimationEdge pre
- param RsAnimationEdge post
- ret RsAnimation
- }
-
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index ec03a15..bff3660 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -15,11 +15,8 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES2/gl2.h>
-#include <GLES/glext.h>
-#endif //ANDROID_RS_SERIALIZE
+#include "rs_hal.h"
+
using namespace android;
using namespace android::renderscript;
@@ -27,308 +24,70 @@ using namespace android::renderscript;
Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages,
RsAllocationMipmapControl mc)
: ObjectBase(rsc) {
- init(rsc, type);
-
- mUsageFlags = usages;
- mMipmapControl = mc;
-
- allocScriptMemory();
- if (mType->getElement()->getHasReferences()) {
- memset(mPtr, 0, mType->getSizeBytes());
- }
- if (!mPtr) {
- LOGE("Allocation::Allocation, alloc failure");
- }
-}
-
-
-void Allocation::init(Context *rsc, const Type *type) {
- mPtr = NULL;
-
- mCpuWrite = false;
- mCpuRead = false;
- mGpuWrite = false;
- mGpuRead = false;
-
- mReadWriteRatio = 0;
- mUpdateSize = 0;
- mUsageFlags = 0;
- mMipmapControl = RS_ALLOCATION_MIPMAP_NONE;
-
- mTextureID = 0;
- mBufferID = 0;
- mUploadDefered = false;
-
- mUserBitmapCallback = NULL;
- mUserBitmapCallbackData = NULL;
-
- mType.set(type);
- rsAssert(type);
-
- mPtr = NULL;
-}
-
-Allocation::~Allocation() {
- if (mUserBitmapCallback != NULL) {
- mUserBitmapCallback(mUserBitmapCallbackData);
- mPtr = NULL;
- }
- freeScriptMemory();
-#ifndef ANDROID_RS_SERIALIZE
- if (mBufferID) {
- // Causes a SW crash....
- //LOGV(" mBufferID %i", mBufferID);
- //glDeleteBuffers(1, &mBufferID);
- //mBufferID = 0;
- }
- if (mTextureID) {
- glDeleteTextures(1, &mTextureID);
- mTextureID = 0;
- }
-#endif //ANDROID_RS_SERIALIZE
-}
-void Allocation::setCpuWritable(bool) {
-}
-
-void Allocation::setGpuWritable(bool) {
-}
-
-void Allocation::setCpuReadable(bool) {
-}
-
-void Allocation::setGpuReadable(bool) {
-}
+ memset(&mHal, 0, sizeof(mHal));
+ mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
+ mHal.state.usageFlags = usages;
+ mHal.state.mipmapControl = mc;
-bool Allocation::fixAllocation() {
- return false;
+ mHal.state.type.set(type);
+ updateCache();
}
-void Allocation::deferedUploadToTexture(const Context *rsc) {
- mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
- mUploadDefered = true;
-}
+Allocation * Allocation::createAllocation(Context *rsc, const Type *type, uint32_t usages,
+ RsAllocationMipmapControl mc) {
+ Allocation *a = new Allocation(rsc, type, usages, mc);
-uint32_t Allocation::getGLTarget() const {
-#ifndef ANDROID_RS_SERIALIZE
- if (getIsTexture()) {
- if (mType->getDimFaces()) {
- return GL_TEXTURE_CUBE_MAP;
- } else {
- return GL_TEXTURE_2D;
- }
- }
- if (getIsBufferObject()) {
- return GL_ARRAY_BUFFER;
+ if (!rsc->mHal.funcs.allocation.init(rsc, a, type->getElement()->getHasReferences())) {
+ rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
+ delete a;
+ return NULL;
}
-#endif //ANDROID_RS_SERIALIZE
- return 0;
+ return a;
}
-void Allocation::allocScriptMemory() {
- rsAssert(!mPtr);
- mPtr = malloc(mType->getSizeBytes());
+void Allocation::updateCache() {
+ const Type *type = mHal.state.type.get();
+ mHal.state.dimensionX = type->getDimX();
+ mHal.state.dimensionY = type->getDimY();
+ mHal.state.dimensionZ = type->getDimZ();
+ mHal.state.hasFaces = type->getDimFaces();
+ mHal.state.hasMipmaps = type->getDimLOD();
+ mHal.state.elementSizeBytes = type->getElementSizeBytes();
+ mHal.state.hasReferences = mHal.state.type->getElement()->getHasReferences();
}
-void Allocation::freeScriptMemory() {
- if (mPtr) {
- free(mPtr);
- mPtr = NULL;
- }
+Allocation::~Allocation() {
+ mRSC->mHal.funcs.allocation.destroy(mRSC, this);
}
-
void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) {
- rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
-
- if (getIsTexture()) {
- uploadToTexture(rsc);
- }
- if (getIsBufferObject()) {
- uploadToBufferObject(rsc);
- }
-
- mUploadDefered = false;
-}
-
-void Allocation::uploadToTexture(const Context *rsc) {
-#ifndef ANDROID_RS_SERIALIZE
- mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
- GLenum type = mType->getElement()->getComponent().getGLType();
- GLenum format = mType->getElement()->getComponent().getGLFormat();
-
- if (!type || !format) {
- return;
- }
-
- if (!mPtr) {
- return;
- }
-
- bool isFirstUpload = false;
-
- if (!mTextureID) {
- glGenTextures(1, &mTextureID);
-
- if (!mTextureID) {
- // This should not happen, however, its likely the cause of the
- // white sqare bug.
- // Force a crash to 1: restart the app, 2: make sure we get a bugreport.
- LOGE("Upload to texture failed to gen mTextureID");
- rsc->dumpDebug();
- mUploadDefered = true;
- return;
- }
- isFirstUpload = true;
- }
-
- upload2DTexture(isFirstUpload);
-
- if (!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
- freeScriptMemory();
- }
-
- rsc->checkError("Allocation::uploadToTexture");
-#endif //ANDROID_RS_SERIALIZE
-}
-
-#ifndef ANDROID_RS_SERIALIZE
-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
-};
-#endif //ANDROID_RS_SERIALIZE
-
-void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
- uint32_t lod, RsAllocationCubemapFace face,
- uint32_t w, uint32_t h) {
-#ifndef ANDROID_RS_SERIALIZE
- GLenum type = mType->getElement()->getComponent().getGLType();
- GLenum format = mType->getElement()->getComponent().getGLFormat();
- GLenum target = (GLenum)getGLTarget();
- rsAssert(mTextureID);
- glBindTexture(target, mTextureID);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- GLenum t = GL_TEXTURE_2D;
- if (mType->getDimFaces()) {
- t = gFaceOrder[face];
- }
- glTexSubImage2D(t, lod, xoff, yoff, w, h, format, type, ptr);
-#endif //ANDROID_RS_SERIALIZE
-}
-
-void Allocation::upload2DTexture(bool isFirstUpload) {
-#ifndef ANDROID_RS_SERIALIZE
- GLenum type = mType->getElement()->getComponent().getGLType();
- GLenum format = mType->getElement()->getComponent().getGLFormat();
-
- GLenum target = (GLenum)getGLTarget();
- glBindTexture(target, mTextureID);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- uint32_t faceCount = 1;
- if (mType->getDimFaces()) {
- faceCount = 6;
- }
-
- for (uint32_t face = 0; face < faceCount; face ++) {
- for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) {
- const uint8_t *p = (const uint8_t *)mPtr;
- p += mType->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0);
-
- GLenum t = GL_TEXTURE_2D;
- if (mType->getDimFaces()) {
- t = gFaceOrder[face];
- }
-
- if (isFirstUpload) {
- glTexImage2D(t, lod, format,
- mType->getLODDimX(lod), mType->getLODDimY(lod),
- 0, format, type, p);
- } else {
- glTexSubImage2D(t, lod, 0, 0,
- mType->getLODDimX(lod), mType->getLODDimY(lod),
- format, type, p);
- }
- }
- }
-
- if (mMipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
- glGenerateMipmap(target);
- }
-#endif //ANDROID_RS_SERIALIZE
-}
-
-void Allocation::deferedUploadToBufferObject(const Context *rsc) {
- mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
- mUploadDefered = true;
-}
-
-void Allocation::uploadToBufferObject(const Context *rsc) {
-#ifndef ANDROID_RS_SERIALIZE
- rsAssert(!mType->getDimY());
- rsAssert(!mType->getDimZ());
-
- mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
-
- if (!mBufferID) {
- glGenBuffers(1, &mBufferID);
- }
- if (!mBufferID) {
- LOGE("Upload to buffer object failed");
- mUploadDefered = true;
- return;
- }
- GLenum target = (GLenum)getGLTarget();
- glBindBuffer(target, mBufferID);
- glBufferData(target, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
- glBindBuffer(target, 0);
- rsc->checkError("Allocation::uploadToBufferObject");
-#endif //ANDROID_RS_SERIALIZE
-}
-
-void Allocation::uploadCheck(Context *rsc) {
- if (mUploadDefered) {
- syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT);
- }
+ rsc->mHal.funcs.allocation.syncAll(rsc, this, src);
}
void Allocation::read(void *data) {
- memcpy(data, mPtr, mType->getSizeBytes());
+ memcpy(data, getPtr(), mHal.state.type->getSizeBytes());
}
void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
uint32_t count, const void *data, uint32_t sizeBytes) {
- uint32_t eSize = mType->getElementSizeBytes();
- uint8_t * ptr = static_cast<uint8_t *>(mPtr);
- ptr += eSize * xoff;
- uint32_t size = count * eSize;
-
- if (size != sizeBytes) {
- LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes);
- mType->dumpLOGV("type info");
- return;
- }
+ const uint32_t eSize = mHal.state.type->getElementSizeBytes();
- if (mType->getElement()->getHasReferences()) {
- incRefs(data, count);
- decRefs(ptr, count);
+ if ((count * eSize) != sizeBytes) {
+ LOGE("Allocation::subData called with mismatched size expected %i, got %i",
+ (count * eSize), sizeBytes);
+ mHal.state.type->dumpLOGV("type info");
+ return;
}
- memcpy(ptr, data, size);
- sendDirty();
- mUploadDefered = true;
+ rsc->mHal.funcs.allocation.data1D(rsc, this, xoff, lod, count, data, sizeBytes);
+ sendDirty(rsc);
}
void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
- uint32_t eSize = mType->getElementSizeBytes();
- uint32_t lineSize = eSize * w;
- uint32_t destW = mType->getDimX();
+ const uint32_t eSize = mHal.state.elementSizeBytes;
+ const uint32_t lineSize = eSize * w;
//LOGE("data2d %p, %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes);
@@ -338,26 +97,8 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod,
return;
}
- if (mPtr) {
- const uint8_t *src = static_cast<const uint8_t *>(data);
- uint8_t *dst = static_cast<uint8_t *>(mPtr);
- dst += mType->getLODFaceOffset(lod, face, xoff, yoff);
-
- //LOGE(" %p %p %i ", dst, src, eSize);
- for (uint32_t line=yoff; line < (yoff+h); line++) {
- if (mType->getElement()->getHasReferences()) {
- incRefs(src, w);
- decRefs(dst, w);
- }
- memcpy(dst, src, lineSize);
- src += lineSize;
- dst += destW * eSize;
- }
- sendDirty();
- mUploadDefered = true;
- } else {
- update2DTexture(data, xoff, yoff, lod, face, w, h);
- }
+ rsc->mHal.funcs.allocation.data2D(rsc, this, xoff, yoff, lod, face, w, h, data, sizeBytes);
+ sendDirty(rsc);
}
void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
@@ -367,67 +108,54 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
uint32_t cIdx, uint32_t sizeBytes) {
- uint32_t eSize = mType->getElementSizeBytes();
- uint8_t * ptr = static_cast<uint8_t *>(mPtr);
- ptr += eSize * x;
+ uint32_t eSize = mHal.state.elementSizeBytes;
- if (cIdx >= mType->getElement()->getFieldCount()) {
+ if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
return;
}
- if (x >= mType->getDimX()) {
+ if (x >= mHal.state.dimensionX) {
LOGE("Error Allocation::subElementData X offset %i out of range.", x);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
return;
}
- const Element * e = mType->getElement()->getField(cIdx);
- ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
-
+ const Element * e = mHal.state.type->getElement()->getField(cIdx);
if (sizeBytes != e->getSizeBytes()) {
LOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes());
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
return;
}
- if (e->getHasReferences()) {
- e->incRefs(data);
- e->decRefs(ptr);
- }
-
- memcpy(ptr, data, sizeBytes);
- sendDirty();
- mUploadDefered = true;
+ rsc->mHal.funcs.allocation.elementData1D(rsc, this, x, data, cIdx, sizeBytes);
+ sendDirty(rsc);
}
void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
const void *data, uint32_t cIdx, uint32_t sizeBytes) {
- uint32_t eSize = mType->getElementSizeBytes();
- uint8_t * ptr = static_cast<uint8_t *>(mPtr);
- ptr += eSize * (x + y * mType->getDimX());
+ uint32_t eSize = mHal.state.elementSizeBytes;
- if (x >= mType->getDimX()) {
+ if (x >= mHal.state.dimensionX) {
LOGE("Error Allocation::subElementData X offset %i out of range.", x);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
return;
}
- if (y >= mType->getDimY()) {
+ if (y >= mHal.state.dimensionY) {
LOGE("Error Allocation::subElementData X offset %i out of range.", x);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
return;
}
- if (cIdx >= mType->getElement()->getFieldCount()) {
+ if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
return;
}
- const Element * e = mType->getElement()->getField(cIdx);
- ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
+ const Element * e = mHal.state.type->getElement()->getField(cIdx);
if (sizeBytes != e->getSizeBytes()) {
LOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes());
@@ -435,24 +163,15 @@ void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
return;
}
- if (e->getHasReferences()) {
- e->incRefs(data);
- e->decRefs(ptr);
- }
-
- memcpy(ptr, data, sizeBytes);
- sendDirty();
- mUploadDefered = true;
+ rsc->mHal.funcs.allocation.elementData2D(rsc, this, x, y, data, cIdx, sizeBytes);
+ sendDirty(rsc);
}
void Allocation::addProgramToDirty(const Program *p) {
-#ifndef ANDROID_RS_SERIALIZE
mToDirtyList.push(p);
-#endif //ANDROID_RS_SERIALIZE
}
void Allocation::removeProgramToDirty(const Program *p) {
-#ifndef ANDROID_RS_SERIALIZE
for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
if (mToDirtyList[ct] == p) {
mToDirtyList.removeAt(ct);
@@ -460,7 +179,6 @@ void Allocation::removeProgramToDirty(const Program *p) {
}
}
rsAssert(0);
-#endif //ANDROID_RS_SERIALIZE
}
void Allocation::dumpLOGV(const char *prefix) const {
@@ -468,15 +186,12 @@ void Allocation::dumpLOGV(const char *prefix) const {
String8 s(prefix);
s.append(" type ");
- if (mType.get()) {
- mType->dumpLOGV(s.string());
+ if (mHal.state.type.get()) {
+ mHal.state.type->dumpLOGV(s.string());
}
- LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i",
- prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead);
-
- LOGV("%s allocation mUsageFlags=0x04%x, mMipmapControl=0x%04x, mTextureID=%i, mBufferID=%i",
- prefix, mUsageFlags, mMipmapControl, mTextureID, mBufferID);
+ LOGV("%s allocation ptr=%p mUsageFlags=0x04%x, mMipmapControl=0x%04x",
+ prefix, getPtr(), mHal.state.usageFlags, mHal.state.mipmapControl);
}
void Allocation::serialize(OStream *stream) const {
@@ -488,13 +203,13 @@ void Allocation::serialize(OStream *stream) const {
// First thing we need to serialize is the type object since it will be needed
// to initialize the class
- mType->serialize(stream);
+ mHal.state.type->serialize(stream);
- uint32_t dataSize = mType->getSizeBytes();
+ uint32_t dataSize = mHal.state.type->getSizeBytes();
// Write how much data we are storing
stream->addU32(dataSize);
// Now write the data
- stream->addByteArray(mPtr, dataSize);
+ stream->addByteArray(getPtr(), dataSize);
}
Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
@@ -522,7 +237,7 @@ Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
return NULL;
}
- Allocation *alloc = new Allocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
+ Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
alloc->setName(name.string(), name.size());
uint32_t count = dataSize / type->getElementSizeBytes();
@@ -534,17 +249,16 @@ Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
return alloc;
}
-void Allocation::sendDirty() const {
-#ifndef ANDROID_RS_SERIALIZE
+void Allocation::sendDirty(const Context *rsc) const {
for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
mToDirtyList[ct]->forceDirty();
}
-#endif //ANDROID_RS_SERIALIZE
+ mRSC->mHal.funcs.allocation.markDirty(rsc, this);
}
void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const {
const uint8_t *p = static_cast<const uint8_t *>(ptr);
- const Element *e = mType->getElement();
+ const Element *e = mHal.state.type->getElement();
uint32_t stride = e->getSizeBytes();
p += stride * startOff;
@@ -557,7 +271,7 @@ void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const {
void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const {
const uint8_t *p = static_cast<const uint8_t *>(ptr);
- const Element *e = mType->getElement();
+ const Element *e = mHal.state.type->getElement();
uint32_t stride = e->getSizeBytes();
p += stride * startOff;
@@ -572,24 +286,18 @@ void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff
}
void Allocation::resize1D(Context *rsc, uint32_t dimX) {
- Type *t = mType->cloneAndResize1D(rsc, dimX);
-
- uint32_t oldDimX = mType->getDimX();
+ uint32_t oldDimX = mHal.state.dimensionX;
if (dimX == oldDimX) {
return;
}
+ Type *t = mHal.state.type->cloneAndResize1D(rsc, dimX);
if (dimX < oldDimX) {
- decRefs(mPtr, oldDimX - dimX, dimX);
+ decRefs(getPtr(), oldDimX - dimX, dimX);
}
- mPtr = realloc(mPtr, t->getSizeBytes());
-
- if (dimX > oldDimX) {
- const Element *e = mType->getElement();
- uint32_t stride = e->getSizeBytes();
- memset(((uint8_t *)mPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
- }
- mType.set(t);
+ rsc->mHal.funcs.allocation.resize(rsc, this, t, mHal.state.hasReferences);
+ mHal.state.type.set(t);
+ updateCache();
}
void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) {
@@ -598,22 +306,11 @@ void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) {
/////////////////
//
-#ifndef ANDROID_RS_SERIALIZE
-
-static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va);
namespace android {
namespace renderscript {
-void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel) {
- Allocation *alloc = static_cast<Allocation *>(va);
- alloc->deferedUploadToTexture(rsc);
-}
-
-void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) {
- Allocation *alloc = static_cast<Allocation *>(va);
- alloc->deferedUploadToBufferObject(rsc);
-}
+static void AllocationGenerateScriptMips(RsContext con, RsAllocation va);
static void mip565(const Adapter2D &out, const Adapter2D &in) {
uint32_t w = out.getDimX();
@@ -685,13 +382,13 @@ static void mip(const Adapter2D &out, const Adapter2D &in) {
void rsi_AllocationSyncAll(Context *rsc, RsAllocation va, RsAllocationUsageType src) {
Allocation *a = static_cast<Allocation *>(va);
+ a->sendDirty(rsc);
a->syncAll(rsc, src);
- a->sendDirty();
}
void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) {
Allocation *texAlloc = static_cast<Allocation *>(va);
- rsaAllocationGenerateScriptMips(rsc, texAlloc);
+ AllocationGenerateScriptMips(rsc, texAlloc);
}
void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
@@ -708,30 +405,30 @@ void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_
}
void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
- uint32_t count, const void *data, uint32_t sizeBytes) {
+ uint32_t count, const void *data, size_t sizeBytes) {
Allocation *a = static_cast<Allocation *>(va);
a->data(rsc, xoff, lod, count, data, sizeBytes);
}
void rsi_Allocation2DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t lod, RsAllocationCubemapFace face,
- const void *data, uint32_t eoff, uint32_t sizeBytes) {
+ const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped
Allocation *a = static_cast<Allocation *>(va);
a->elementData(rsc, x, y, data, eoff, sizeBytes);
}
void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t lod,
- const void *data, uint32_t eoff, uint32_t sizeBytes) {
+ const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped
Allocation *a = static_cast<Allocation *>(va);
a->elementData(rsc, x, data, eoff, sizeBytes);
}
void rsi_Allocation2DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
- uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
+ uint32_t w, uint32_t h, const void *data, size_t sizeBytes) {
Allocation *a = static_cast<Allocation *>(va);
a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes);
}
-void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) {
+void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data, size_t data_length) {
Allocation *a = static_cast<Allocation *>(va);
a->read(data);
}
@@ -746,10 +443,7 @@ void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32
a->resize2D(rsc, dimX, dimY);
}
-}
-}
-
-static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va) {
+static void AllocationGenerateScriptMips(RsContext con, RsAllocation va) {
Context *rsc = static_cast<Context *>(con);
Allocation *texAlloc = static_cast<Allocation *>(va);
uint32_t numFaces = texAlloc->getType()->getDimFaces() ? 6 : 1;
@@ -766,30 +460,23 @@ static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va) {
}
}
-const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
- Allocation *a = static_cast<Allocation *>(va);
- a->getType()->incUserRef();
-
- return a->getType();
-}
-
-RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- uint32_t usages) {
- Context *rsc = static_cast<Context *>(con);
- Allocation * alloc = new Allocation(rsc, static_cast<Type *>(vtype), usages, mips);
+RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype,
+ RsAllocationMipmapControl mips,
+ uint32_t usages) {
+ Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mips);
+ if (!alloc) {
+ return NULL;
+ }
alloc->incUserRef();
return alloc;
}
-
-RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- const void *data, uint32_t usages) {
- Context *rsc = static_cast<Context *>(con);
+RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, RsType vtype,
+ RsAllocationMipmapControl mips,
+ const void *data, size_t data_length, uint32_t usages) {
Type *t = static_cast<Type *>(vtype);
- RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, vtype, mips, usages);
+ RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
if (texAlloc == NULL) {
LOGE("Memory allocation failure");
@@ -798,23 +485,22 @@ RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes());
if (mips == RS_ALLOCATION_MIPMAP_FULL) {
- rsaAllocationGenerateScriptMips(rsc, texAlloc);
+ AllocationGenerateScriptMips(rsc, texAlloc);
}
- texAlloc->deferedUploadToTexture(rsc);
+ texAlloc->sendDirty(rsc);
return texAlloc;
}
-RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- const void *data, uint32_t usages) {
- Context *rsc = static_cast<Context *>(con);
+RsAllocation rsi_AllocationCubeCreateFromBitmap(Context *rsc, RsType vtype,
+ RsAllocationMipmapControl mips,
+ const void *data, size_t data_length, uint32_t usages) {
Type *t = static_cast<Type *>(vtype);
// Cubemap allocation's faces should be Width by Width each.
// Source data should have 6 * Width by Width pixels
// Error checking is done in the java layer
- RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, t, mips, usages);
+ RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
if (texAlloc == NULL) {
LOGE("Memory allocation failure");
@@ -839,11 +525,19 @@ RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
}
if (mips == RS_ALLOCATION_MIPMAP_FULL) {
- rsaAllocationGenerateScriptMips(rsc, texAlloc);
+ AllocationGenerateScriptMips(rsc, texAlloc);
}
- texAlloc->deferedUploadToTexture(rsc);
+ texAlloc->sendDirty(rsc);
return texAlloc;
}
-#endif //ANDROID_RS_SERIALIZE
+}
+}
+
+const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
+ Allocation *a = static_cast<Allocation *>(va);
+ a->getType()->incUserRef();
+
+ return a->getType();
+}
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index 4f5d5a8..f538dd1 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -29,33 +29,44 @@ class Allocation : public ObjectBase {
// The graphics equilivent of malloc. The allocation contains a structure of elements.
public:
- Allocation(Context *rsc, const Type *, uint32_t usages,
- RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE);
-
+ struct Hal {
+ void * drv;
+
+ struct State {
+ ObjectBaseRef<const Type> type;
+
+ uint32_t usageFlags;
+ RsAllocationMipmapControl mipmapControl;
+
+ // Cached fields from the Type and Element
+ // to prevent pointer chasing in critical loops.
+ uint32_t dimensionX;
+ uint32_t dimensionY;
+ uint32_t dimensionZ;
+ uint32_t elementSizeBytes;
+ bool hasMipmaps;
+ bool hasFaces;
+ bool hasReferences;
+ };
+ State state;
+
+ struct DrvState {
+ void * mallocPtr;
+ } drvState;
+
+ };
+ Hal mHal;
+
+ static Allocation * createAllocation(Context *rsc, const Type *, uint32_t usages,
+ RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE);
virtual ~Allocation();
+ void updateCache();
- void setCpuWritable(bool);
- void setGpuWritable(bool);
- void setCpuReadable(bool);
- void setGpuReadable(bool);
-
- bool fixAllocation();
-
- void * getPtr() const {return mPtr;}
- const Type * getType() const {return mType.get();}
+ void * getPtr() const {return mHal.drvState.mallocPtr;}
+ const Type * getType() const {return mHal.state.type.get();}
void syncAll(Context *rsc, RsAllocationUsageType src);
- void deferedUploadToTexture(const Context *rsc);
- void uploadToTexture(const Context *rsc);
- uint32_t getTextureID() const {return mTextureID;}
-
- uint32_t getGLTarget() const;
-
- void deferedUploadToBufferObject(const Context *rsc);
- void uploadToBufferObject(const Context *rsc);
- uint32_t getBufferObjectID() const {return mBufferID;}
-
void copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len);
void resize1D(Context *rsc, uint32_t dimX);
@@ -74,9 +85,6 @@ public:
void read(void *data);
- void enableGLVertexBuffers() const;
- void setupGLIndexBuffers() const;
-
void addProgramToDirty(const Program *);
void removeProgramToDirty(const Program *);
@@ -85,74 +93,33 @@ public:
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ALLOCATION; }
static Allocation *createFromStream(Context *rsc, IStream *stream);
- virtual void uploadCheck(Context *rsc);
-
bool getIsScript() const {
- return (mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT) != 0;
+ return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) != 0;
}
bool getIsTexture() const {
- return (mUsageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) != 0;
+ return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) != 0;
+ }
+ bool getIsRenderTarget() const {
+ return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) != 0;
}
bool getIsBufferObject() const {
- return (mUsageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) != 0;
+ return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) != 0;
}
void incRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
void decRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
- void sendDirty() const;
+ void sendDirty(const Context *rsc) const;
bool getHasGraphicsMipmaps() const {
- return mMipmapControl != RS_ALLOCATION_MIPMAP_NONE;
+ return mHal.state.mipmapControl != RS_ALLOCATION_MIPMAP_NONE;
}
protected:
- ObjectBaseRef<const Type> mType;
- void * mPtr;
-
Vector<const Program *> mToDirtyList;
- // Is we have a non-null user bitmap callback we do not own the bits and
- // instead call this function to free the memort when its time.
- RsBitmapCallback_t mUserBitmapCallback;
- void *mUserBitmapCallbackData;
-
- // Usage restrictions
- bool mCpuWrite;
- bool mCpuRead;
- bool mGpuWrite;
- bool mGpuRead;
-
- uint32_t mUsageFlags;
- RsAllocationMipmapControl mMipmapControl;
-
- // more usage hint data from the application
- // which can be used by a driver to pick the best memory type.
- // Likely ignored for now
- float mReadWriteRatio;
- float mUpdateSize;
-
-
- // Is this a legal structure to be used as a texture source.
- // Initially this will require 1D or 2D and color data
- uint32_t mTextureID;
-
- // 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 mBufferID;
-
- bool mUploadDefered;
-
private:
- void init(Context *rsc, const Type *);
- void upload2DTexture(bool isFirstUpload);
- void update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
- uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h);
-
- void allocScriptMemory();
- void freeScriptMemory();
-
+ Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc);
};
}
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index 4c4987a..e65febb 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -16,10 +16,6 @@
#include "rsComponent.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#endif
-
using namespace android;
using namespace android::renderscript;
@@ -180,39 +176,6 @@ bool Component::isReference() const {
return (mType >= RS_TYPE_ELEMENT);
}
-uint32_t Component::getGLType() const {
-#ifndef ANDROID_RS_SERIALIZE
- switch (mType) {
- 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;
- }
-#endif //ANDROID_RS_SERIALIZE
- return 0;
-}
-
-uint32_t Component::getGLFormat() const {
-#ifndef ANDROID_RS_SERIALIZE
- switch (mKind) {
- 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;
- default: break;
- }
-#endif //ANDROID_RS_SERIALIZE
- return 0;
-}
-
String8 Component::getGLSLType() const {
if (mType == RS_TYPE_SIGNED_32) {
switch (mVectorSize) {
@@ -242,6 +205,7 @@ String8 Component::getGLSLType() const {
return String8();
}
+
static const char * gTypeBasicStrings[] = {
"NONE",
"F16",
diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h
index 1bb4ff4..a448f0e 100644
--- a/libs/rs/rsComponent.h
+++ b/libs/rs/rsComponent.h
@@ -32,8 +32,6 @@ public:
void set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize=1);
- uint32_t getGLType() const;
- uint32_t getGLFormat() const;
String8 getGLSLType() const;
void dumpLOGV(const char *prefix) const;
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index c63d183..44e9d89 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -18,9 +18,6 @@
#include "rsContext.h"
#include "rsThreadIO.h"
#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>
@@ -28,11 +25,6 @@
#include <cutils/properties.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
#include <cutils/sched_policy.h>
#include <sys/syscall.h>
#include <string.h>
@@ -40,232 +32,26 @@
using namespace android;
using namespace android::renderscript;
-pthread_key_t Context::gThreadTLSKey = 0;
-uint32_t Context::gThreadTLSKeyCount = 0;
-uint32_t Context::gGLContextCount = 0;
pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
-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);
- }
-}
-
-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);
- }
- }
-}
-
-
bool Context::initGLThread() {
pthread_mutex_lock(&gInitMutex);
LOGV("initGLThread start %p", this);
- mEGL.mNumConfigs = -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 (mUserSurfaceConfig.depthMin > 0) {
- configAttribsPtr[0] = EGL_DEPTH_SIZE;
- configAttribsPtr[1] = mUserSurfaceConfig.depthMin;
- configAttribsPtr += 2;
- }
-
- if (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", this);
- mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- checkEglError("eglGetDisplay");
-
- eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);
- checkEglError("eglInitialize");
-
-#if 1
- PixelFormat pf = PIXEL_FORMAT_RGBA_8888;
- if (mUserSurfaceConfig.alphaMin == 0) {
- pf = PIXEL_FORMAT_RGBX_8888;
- }
-
- status_t err = EGLUtils::selectConfigForPixelFormat(mEGL.mDisplay, configAttribs, pf, &mEGL.mConfig);
- if (err) {
- LOGE("%p, couldn't find an EGLConfig matching the screen format\n", this);
- }
- if (props.mLogVisual) {
- printEGLConfiguration(mEGL.mDisplay, mEGL.mConfig);
- }
-#else
- eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs);
-#endif
-
- mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, context_attribs2);
- checkEglError("eglCreateContext");
- if (mEGL.mContext == EGL_NO_CONTEXT) {
- pthread_mutex_unlock(&gInitMutex);
- LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", this);
- return false;
- }
- gGLContextCount++;
-
-
- EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
- mEGL.mSurfaceDefault = eglCreatePbufferSurface(mEGL.mDisplay, mEGL.mConfig, pbuffer_attribs);
- checkEglError("eglCreatePbufferSurface");
- if (mEGL.mSurfaceDefault == EGL_NO_SURFACE) {
- LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE");
- pthread_mutex_unlock(&gInitMutex);
- deinitEGL();
- return false;
- }
-
- EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurfaceDefault, mEGL.mSurfaceDefault, mEGL.mContext);
- if (ret == EGL_FALSE) {
- LOGE("eglMakeCurrent returned EGL_FALSE");
- checkEglError("eglMakeCurrent", ret);
- pthread_mutex_unlock(&gInitMutex);
- deinitEGL();
- return false;
- }
-
- mGL.mVersion = glGetString(GL_VERSION);
- mGL.mVendor = glGetString(GL_VENDOR);
- mGL.mRenderer = glGetString(GL_RENDERER);
- mGL.mExtensions = 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 *)mGL.mVersion) > 9) {
- if (!memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
- verptr = (const char *)mGL.mVersion + 12;
- }
- if (!memcmp(mGL.mVersion, "OpenGL ES ", 10)) {
- verptr = (const char *)mGL.mVersion + 9;
- }
- }
-
- if (!verptr) {
- LOGE("Error, OpenGL ES Lite not supported");
+ if (!mHal.funcs.initGraphics(this)) {
pthread_mutex_unlock(&gInitMutex);
- deinitEGL();
+ LOGE("%p, initGraphics failed", this);
return false;
- } else {
- sscanf(verptr, " %i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
}
- glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mGL.mMaxVertexAttribs);
- glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &mGL.mMaxVertexUniformVectors);
- glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGL.mMaxVertexTextureUnits);
-
- glGetIntegerv(GL_MAX_VARYING_VECTORS, &mGL.mMaxVaryingVectors);
- glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGL.mMaxTextureImageUnits);
-
- glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mGL.mMaxFragmentTextureImageUnits);
- glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors);
-
- mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot");
- mGL.GL_IMG_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_IMG_texture_npot");
- mGL.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)mGL.mExtensions, "GL_NV_texture_npot_2D_mipmap");
- mGL.EXT_texture_max_aniso = 1.0f;
- bool hasAniso = NULL != strstr((const char *)mGL.mExtensions, "GL_EXT_texture_filter_anisotropic");
- if (hasAniso) {
- glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mGL.EXT_texture_max_aniso);
- }
-
- LOGV("initGLThread end %p", this);
pthread_mutex_unlock(&gInitMutex);
return true;
}
void Context::deinitEGL() {
LOGV("%p, deinitEGL", this);
-
- if (mEGL.mContext != EGL_NO_CONTEXT) {
- eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroySurface(mEGL.mDisplay, mEGL.mSurfaceDefault);
- if (mEGL.mSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mEGL.mDisplay, mEGL.mSurface);
- }
- eglDestroyContext(mEGL.mDisplay, mEGL.mContext);
- checkEglError("eglDestroyContext");
- }
-
- gGLContextCount--;
- if (!gGLContextCount) {
- eglTerminate(mEGL.mDisplay);
- }
+ mHal.funcs.shutdownGraphics(this);
}
Context::PushState::PushState(Context *con) {
@@ -297,45 +83,22 @@ uint32_t Context::runScript(Script *s) {
return ret;
}
-void Context::checkError(const char *msg, bool isFatal) const {
-
- 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) {
- setError(RS_ERROR_FATAL_DRIVER, buf);
- } else {
- switch (err) {
- case GL_OUT_OF_MEMORY:
- setError(RS_ERROR_OUT_OF_MEMORY, buf);
- break;
- default:
- setError(RS_ERROR_DRIVER, buf);
- break;
- }
- }
-
- LOGE("%p, %s", this, buf);
- }
-}
-
uint32_t Context::runRootScript() {
- glViewport(0, 0, mWidth, mHeight);
-
timerSet(RS_TIMER_SCRIPT);
mStateFragmentStore.mLast.clear();
uint32_t ret = runScript(mRootScript.get());
- checkError("runRootScript");
return ret;
}
uint64_t Context::getTime() const {
+#ifndef ANDROID_RS_SERIALIZE
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
+#else
+ return 0;
+#endif //ANDROID_RS_SERIALIZE
}
void Context::timerReset() {
@@ -400,20 +163,17 @@ void Context::timerPrint() {
}
bool Context::setupCheck() {
- if (!mShaderCache.lookup(this, mVertex.get(), mFragment.get())) {
- LOGE("Context::setupCheck() 1 fail");
- return false;
- }
- mFragmentStore->setupGL2(this, &mStateFragmentStore);
- mFragment->setupGL2(this, &mStateFragment, &mShaderCache);
- mRaster->setupGL2(this, &mStateRaster);
- mVertex->setupGL2(this, &mStateVertex, &mShaderCache);
+ mFragmentStore->setup(this, &mStateFragmentStore);
+ mFragment->setup(this, &mStateFragment);
+ mRaster->setup(this, &mStateRaster);
+ mVertex->setup(this, &mStateVertex);
+ mFBOCache.setup(this);
return true;
}
void Context::setupProgramStore() {
- mFragmentStore->setupGL2(this, &mStateFragmentStore);
+ mFragmentStore->setup(this, &mStateFragmentStore);
}
static bool getProp(const char *str) {
@@ -429,6 +189,8 @@ void Context::displayDebugStats() {
mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA);
uint32_t bufferLen = strlen(buffer);
+ ObjectBaseRef<Font> lastFont(getFont());
+ setFont(NULL);
float shadowCol = 0.1f;
mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f);
mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6);
@@ -436,98 +198,92 @@ void Context::displayDebugStats() {
mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f);
mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7);
+ setFont(lastFont.get());
mStateFont.setFontColor(oldR, oldG, oldB, oldA);
}
void * Context::threadProc(void *vrsc) {
- Context *rsc = static_cast<Context *>(vrsc);
- rsc->mNativeThreadId = gettid();
-
- setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY);
- rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY;
-
- rsc->props.mLogTimes = getProp("debug.rs.profile");
- rsc->props.mLogScripts = getProp("debug.rs.script");
- rsc->props.mLogObjects = getProp("debug.rs.object");
- rsc->props.mLogShaders = getProp("debug.rs.shader");
- rsc->props.mLogShadersAttr = getProp("debug.rs.shader.attributes");
- rsc->props.mLogShadersUniforms = getProp("debug.rs.shader.uniforms");
- rsc->props.mLogVisual = getProp("debug.rs.visual");
-
- rsc->mTlsStruct = new ScriptTLSStruct;
- if (!rsc->mTlsStruct) {
- LOGE("Error allocating tls storage");
- rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed allocation for TLS");
- return NULL;
- }
- rsc->mTlsStruct->mContext = rsc;
- rsc->mTlsStruct->mScript = NULL;
- int status = pthread_setspecific(rsc->gThreadTLSKey, rsc->mTlsStruct);
- if (status) {
- LOGE("pthread_setspecific %i", status);
- }
-
- if (!rsc->initGLThread()) {
- rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed initializing GL");
- return NULL;
- }
-
- if (rsc->mIsGraphicsContext) {
- rsc->mStateRaster.init(rsc);
- rsc->setProgramRaster(NULL);
- rsc->mStateVertex.init(rsc);
- rsc->setProgramVertex(NULL);
- rsc->mStateFragment.init(rsc);
- rsc->setProgramFragment(NULL);
- rsc->mStateFragmentStore.init(rsc);
- rsc->setProgramStore(NULL);
- rsc->mStateFont.init(rsc);
- rsc->setFont(NULL);
- rsc->mStateVertexArray.init(rsc);
- }
-
- rsc->mRunning = true;
- bool mDraw = true;
- while (!rsc->mExit) {
- mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
- mDraw &= (rsc->mRootScript.get() != NULL);
- mDraw &= (rsc->mWndSurface != NULL);
-
- uint32_t targetTime = 0;
- if (mDraw && rsc->mIsGraphicsContext) {
- targetTime = rsc->runRootScript();
-
- if (rsc->props.mLogVisual) {
- rsc->displayDebugStats();
- }
-
- mDraw = targetTime && !rsc->mPaused;
- rsc->timerSet(RS_TIMER_CLEAR_SWAP);
- eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
- rsc->timerFrame();
- rsc->timerSet(RS_TIMER_INTERNAL);
- rsc->timerPrint();
- rsc->timerReset();
- }
- if (targetTime > 1) {
- int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000;
- if (t > 0) {
- usleep(t);
- }
- }
- }
-
- LOGV("%p, RS Thread exiting", rsc);
-
- if (rsc->mIsGraphicsContext) {
- pthread_mutex_lock(&gInitMutex);
- rsc->deinitEGL();
- pthread_mutex_unlock(&gInitMutex);
- }
- delete rsc->mTlsStruct;
-
- LOGV("%p, RS Thread exited", rsc);
- return NULL;
+ Context *rsc = static_cast<Context *>(vrsc);
+#ifndef ANDROID_RS_SERIALIZE
+ rsc->mNativeThreadId = gettid();
+ setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY);
+ rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY;
+#endif //ANDROID_RS_SERIALIZE
+ rsc->props.mLogTimes = getProp("debug.rs.profile");
+ rsc->props.mLogScripts = getProp("debug.rs.script");
+ rsc->props.mLogObjects = getProp("debug.rs.object");
+ rsc->props.mLogShaders = getProp("debug.rs.shader");
+ rsc->props.mLogShadersAttr = getProp("debug.rs.shader.attributes");
+ rsc->props.mLogShadersUniforms = getProp("debug.rs.shader.uniforms");
+ rsc->props.mLogVisual = getProp("debug.rs.visual");
+
+ if (!rsdHalInit(rsc, 0, 0)) {
+ rsc->setError(RS_ERROR_FATAL_DRIVER, "Failed initializing GL");
+ LOGE("Hal init failed");
+ return NULL;
+ }
+ rsc->mHal.funcs.setPriority(rsc, rsc->mThreadPriority);
+
+ if (rsc->mIsGraphicsContext) {
+ if (!rsc->initGLThread()) {
+ rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed initializing GL");
+ return NULL;
+ }
+
+ rsc->mStateRaster.init(rsc);
+ rsc->setProgramRaster(NULL);
+ rsc->mStateVertex.init(rsc);
+ rsc->setProgramVertex(NULL);
+ rsc->mStateFragment.init(rsc);
+ rsc->setProgramFragment(NULL);
+ rsc->mStateFragmentStore.init(rsc);
+ rsc->setProgramStore(NULL);
+ rsc->mStateFont.init(rsc);
+ rsc->setFont(NULL);
+ rsc->mFBOCache.init(rsc);
+ }
+
+ rsc->mRunning = true;
+ bool mDraw = true;
+ while (!rsc->mExit) {
+ mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
+ mDraw &= (rsc->mRootScript.get() != NULL);
+ mDraw &= rsc->mHasSurface;
+
+ uint32_t targetTime = 0;
+ if (mDraw && rsc->mIsGraphicsContext) {
+ targetTime = rsc->runRootScript();
+
+ if (rsc->props.mLogVisual) {
+ rsc->displayDebugStats();
+ }
+
+ mDraw = targetTime && !rsc->mPaused;
+ rsc->timerSet(RS_TIMER_CLEAR_SWAP);
+ rsc->mHal.funcs.swap(rsc);
+ rsc->timerFrame();
+ rsc->timerSet(RS_TIMER_INTERNAL);
+ rsc->timerPrint();
+ rsc->timerReset();
+ }
+ if (targetTime > 1) {
+ int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000;
+ if (t > 0) {
+ usleep(t);
+ }
+ }
+ }
+
+ LOGV("%p, RS Thread exiting", rsc);
+
+ if (rsc->mIsGraphicsContext) {
+ pthread_mutex_lock(&gInitMutex);
+ rsc->deinitEGL();
+ pthread_mutex_unlock(&gInitMutex);
+ }
+
+ LOGV("%p, RS Thread exited", rsc);
+ return NULL;
}
void Context::destroyWorkerThreadResources() {
@@ -545,62 +301,12 @@ void Context::destroyWorkerThreadResources() {
mStateFragment.deinit(this);
mStateFragmentStore.deinit(this);
mStateFont.deinit(this);
- mShaderCache.cleanupAll();
+ mFBOCache.deinit(this);
}
//LOGV("destroyWorkerThreadResources 2");
mExit = true;
}
-void * Context::helperThreadProc(void *vrsc) {
- Context *rsc = static_cast<Context *>(vrsc);
- uint32_t idx = (uint32_t)android_atomic_inc(&rsc->mWorkers.mLaunchCount);
-
- //LOGV("RS helperThread starting %p idx=%i", rsc, idx);
-
- rsc->mWorkers.mLaunchSignals[idx].init();
- rsc->mWorkers.mNativeThreadId[idx] = gettid();
-
-#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
-
- setpriority(PRIO_PROCESS, rsc->mWorkers.mNativeThreadId[idx], rsc->mThreadPriority);
- int status = pthread_setspecific(rsc->gThreadTLSKey, rsc->mTlsStruct);
- if (status) {
- LOGE("pthread_setspecific %i", status);
- }
-
- while (!rsc->mExit) {
- rsc->mWorkers.mLaunchSignals[idx].wait();
- if (rsc->mWorkers.mLaunchCallback) {
- rsc->mWorkers.mLaunchCallback(rsc->mWorkers.mLaunchData, idx);
- }
- android_atomic_dec(&rsc->mWorkers.mRunningCount);
- rsc->mWorkers.mCompleteSignal.set();
- }
-
- //LOGV("RS helperThread exited %p idx=%i", rsc, idx);
- return NULL;
-}
-
-void Context::launchThreads(WorkerCallback_t cbk, void *data) {
- mWorkers.mLaunchData = data;
- mWorkers.mLaunchCallback = cbk;
- android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount);
- for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) {
- mWorkers.mLaunchSignals[ct].set();
- }
- while (android_atomic_acquire_load(&mWorkers.mRunningCount) != 0) {
- mWorkers.mCompleteSignal.wait();
- }
-}
-
void Context::setPriority(int32_t p) {
// Note: If we put this in the proper "background" policy
// the wallpapers can become completly unresponsive at times.
@@ -617,9 +323,6 @@ void Context::setPriority(int32_t p) {
}
#else
setpriority(PRIO_PROCESS, mNativeThreadId, p);
- for (uint32_t ct=0; ct < mWorkers.mCount; ct++) {
- setpriority(PRIO_PROCESS, mWorkers.mNativeThreadId[ct], p);
- }
#endif
}
@@ -631,10 +334,16 @@ Context::Context() {
mObjHead = NULL;
mError = RS_ERROR_NONE;
mDPI = 96;
+ mIsContextLite = false;
}
Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc) {
Context * rsc = new Context();
+
+ // Temporary to avoid breaking the tools
+ if (!dev) {
+ return rsc;
+ }
if (!rsc->initContext(dev, sc)) {
delete rsc;
return NULL;
@@ -642,9 +351,17 @@ Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc) {
return rsc;
}
+Context * Context::createContextLite() {
+ Context * rsc = new Context();
+ rsc->mIsContextLite = true;
+ return rsc;
+}
+
bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
pthread_mutex_lock(&gInitMutex);
+ mIO.init();
+
dev->addContext(this);
mDev = dev;
if (sc) {
@@ -653,23 +370,11 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig));
}
- memset(&mEGL, 0, sizeof(mEGL));
- memset(&mGL, 0, sizeof(mGL));
mIsGraphicsContext = sc != NULL;
int status;
pthread_attr_t threadAttr;
- if (!gThreadTLSKeyCount) {
- status = pthread_key_create(&gThreadTLSKey, NULL);
- if (status) {
- LOGE("Failed to init thread tls key.");
- pthread_mutex_unlock(&gInitMutex);
- return false;
- }
- }
- gThreadTLSKeyCount++;
-
pthread_mutex_unlock(&gInitMutex);
// Global init done at this point.
@@ -680,20 +385,11 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
return false;
}
- mWndSurface = NULL;
+ mHasSurface = false;
timerInit();
timerSet(RS_TIMER_INTERNAL);
- int cpu = sysconf(_SC_NPROCESSORS_ONLN);
- LOGV("RS Launching thread(s), reported CPU count %i", cpu);
- if (cpu < 2) cpu = 0;
-
- mWorkers.mCount = (uint32_t)cpu;
- mWorkers.mThreadId = (pthread_t *) calloc(mWorkers.mCount, sizeof(pthread_t));
- mWorkers.mNativeThreadId = (pid_t *) calloc(mWorkers.mCount, sizeof(pid_t));
- mWorkers.mLaunchSignals = new Signal[mWorkers.mCount];
- mWorkers.mLaunchCallback = NULL;
status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
if (status) {
LOGE("Failed to start rs context thread.");
@@ -704,23 +400,10 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
}
if (mError != RS_ERROR_NONE) {
+ LOGE("Errors during thread init");
return false;
}
- mWorkers.mCompleteSignal.init();
- android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount);
- android_atomic_release_store(0, &mWorkers.mLaunchCount);
- for (uint32_t ct=0; ct < mWorkers.mCount; ct++) {
- status = pthread_create(&mWorkers.mThreadId[ct], &threadAttr, helperThreadProc, this);
- if (status) {
- mWorkers.mCount = ct;
- LOGE("Created fewer than expected number of RS threads.");
- break;
- }
- }
- while (android_atomic_acquire_load(&mWorkers.mRunningCount) != 0) {
- usleep(100);
- }
pthread_attr_destroy(&threadAttr);
return true;
}
@@ -728,73 +411,40 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
Context::~Context() {
LOGV("Context::~Context");
- mIO.mToCore.flush();
- rsAssert(mExit);
- mExit = true;
- mPaused = false;
- void *res;
+ if (!mIsContextLite) {
+ mIO.coreFlush();
+ rsAssert(mExit);
+ mExit = true;
+ mPaused = false;
+ void *res;
- mIO.shutdown();
- int status = pthread_join(mThreadId, &res);
+ mIO.shutdown();
+ int status = pthread_join(mThreadId, &res);
- // Cleanup compute threads.
- mWorkers.mLaunchData = NULL;
- mWorkers.mLaunchCallback = NULL;
- android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount);
- for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) {
- mWorkers.mLaunchSignals[ct].set();
- }
- for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) {
- status = pthread_join(mWorkers.mThreadId[ct], &res);
- }
- rsAssert(android_atomic_acquire_load(&mWorkers.mRunningCount) == 0);
+ if (mHal.funcs.shutdownDriver) {
+ mHal.funcs.shutdownDriver(this);
+ }
- // Global structure cleanup.
- pthread_mutex_lock(&gInitMutex);
- if (mDev) {
- mDev->removeContext(this);
- --gThreadTLSKeyCount;
- if (!gThreadTLSKeyCount) {
- pthread_key_delete(gThreadTLSKey);
+ // Global structure cleanup.
+ pthread_mutex_lock(&gInitMutex);
+ if (mDev) {
+ mDev->removeContext(this);
+ mDev = NULL;
}
- mDev = NULL;
+ pthread_mutex_unlock(&gInitMutex);
}
- pthread_mutex_unlock(&gInitMutex);
LOGV("Context::~Context done");
}
-void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) {
+void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) {
rsAssert(mIsGraphicsContext);
+ mHal.funcs.setSurface(this, w, h, sur);
- EGLBoolean ret;
- // WAR: Some drivers fail to handle 0 size surfaces correcntly.
- // Use the pbuffer to avoid this pitfall.
- if ((mEGL.mSurface != NULL) || (w == 0) || (h == 0)) {
- ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurfaceDefault, mEGL.mSurfaceDefault, mEGL.mContext);
- checkEglError("eglMakeCurrent", ret);
-
- ret = eglDestroySurface(mEGL.mDisplay, mEGL.mSurface);
- checkEglError("eglDestroySurface", ret);
-
- mEGL.mSurface = NULL;
- mWidth = 1;
- mHeight = 1;
- }
-
- mWndSurface = sur;
- if (mWndSurface != NULL) {
- mWidth = w;
- mHeight = h;
-
- mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
- checkEglError("eglCreateWindowSurface");
- if (mEGL.mSurface == EGL_NO_SURFACE) {
- LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
- }
-
- ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
- checkEglError("eglMakeCurrent", ret);
+ mHasSurface = sur != NULL;
+ mWidth = w;
+ mHeight = h;
+ if (mWidth && mHeight) {
mStateVertex.updateSize(this);
}
}
@@ -874,69 +524,18 @@ void Context::removeName(ObjectBase *obj) {
}
}
-RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID, bool wait) {
- *receiveLen = 0;
- if (!wait && mIO.mToClient.isEmpty()) {
- return RS_MESSAGE_TO_CLIENT_NONE;
- }
-
- uint32_t bytesData = 0;
- uint32_t commandID = 0;
- const uint32_t *d = (const uint32_t *)mIO.mToClient.get(&commandID, &bytesData);
- *receiveLen = bytesData - sizeof(uint32_t);
- if (bytesData) {
- *subID = d[0];
- }
- return (RsMessageToClientType)commandID;
+RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID) {
+ return (RsMessageToClientType)mIO.getClientHeader(receiveLen, subID);
}
-RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait) {
- //LOGE("getMessageToClient %i %i", bufferLen, wait);
- *receiveLen = 0;
- if (!wait && mIO.mToClient.isEmpty()) {
- return RS_MESSAGE_TO_CLIENT_NONE;
- }
-
- //LOGE("getMessageToClient 2 con=%p", this);
- uint32_t bytesData = 0;
- uint32_t commandID = 0;
- const uint32_t *d = (const uint32_t *)mIO.mToClient.get(&commandID, &bytesData);
- //LOGE("getMessageToClient 3 %i %i", commandID, bytesData);
-
- *receiveLen = bytesData - sizeof(uint32_t);
- *subID = d[0];
-
- //LOGE("getMessageToClient %i %i", commandID, *subID);
- if (bufferLen >= bytesData) {
- memcpy(data, d+1, *receiveLen);
- mIO.mToClient.next();
- return (RsMessageToClientType)commandID;
- }
- return RS_MESSAGE_TO_CLIENT_RESIZE;
+RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen) {
+ return (RsMessageToClientType)mIO.getClientPayload(data, receiveLen, subID, bufferLen);
}
bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID,
uint32_t subID, size_t len, bool waitForSpace) const {
- //LOGE("sendMessageToClient %i %i %i %i", cmdID, subID, len, waitForSpace);
- if (cmdID == 0) {
- LOGE("Attempting to send invalid command 0 to client.");
- return false;
- }
- if (!waitForSpace) {
- if (!mIO.mToClient.makeSpaceNonBlocking(len + 12)) {
- // Not enough room, and not waiting.
- return false;
- }
- }
- //LOGE("sendMessageToClient 2");
- uint32_t *p = (uint32_t *)mIO.mToClient.reserve(len + sizeof(subID));
- p[0] = subID;
- if (len > 0) {
- memcpy(p+1, data, len);
- }
- mIO.mToClient.commit(cmdID, len + sizeof(subID));
- //LOGE("sendMessageToClient 3");
- return true;
+
+ return mIO.sendToClient(cmdID, subID, data, len, waitForSpace);
}
void Context::initToClient() {
@@ -946,7 +545,7 @@ void Context::initToClient() {
}
void Context::deinitToClient() {
- mIO.mToClient.shutdown();
+ mIO.clientShutdown();
}
void Context::setError(RsError e, const char *msg) const {
@@ -959,21 +558,9 @@ void Context::dumpDebug() const {
LOGE("RS Context debug %p", this);
LOGE("RS Context debug");
- LOGE(" EGL ver %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
- LOGE(" EGL context %p surface %p, Display=%p", mEGL.mContext, mEGL.mSurface, mEGL.mDisplay);
- LOGE(" GL vendor: %s", mGL.mVendor);
- LOGE(" GL renderer: %s", mGL.mRenderer);
- LOGE(" GL Version: %s", mGL.mVersion);
- LOGE(" GL Extensions: %s", mGL.mExtensions);
- LOGE(" GL int Versions %i %i", mGL.mMajorVersion, mGL.mMinorVersion);
LOGE(" RS width %i, height %i", mWidth, mHeight);
LOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused);
- LOGE(" RS pThreadID %li, nativeThreadID %i", mThreadId, mNativeThreadId);
-
- LOGV("MAX Textures %i, %i %i", mGL.mMaxVertexTextureUnits, mGL.mMaxFragmentTextureImageUnits, mGL.mMaxTextureImageUnits);
- LOGV("MAX Attribs %i", mGL.mMaxVertexAttribs);
- LOGV("MAX Uniforms %i, %i", mGL.mMaxVertexUniformVectors, mGL.mMaxFragmentUniformVectors);
- LOGV("MAX Varyings %i", mGL.mMaxVaryingVectors);
+ LOGE(" RS pThreadID %li, nativeThreadID %i", (long int)mThreadId, mNativeThreadId);
}
///////////////////////////////////////////////////////////////////////////////////////////
@@ -1026,9 +613,9 @@ void rsi_ContextBindFont(Context *rsc, RsFont vfont) {
rsc->setFont(font);
}
-void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len) {
+void rsi_AssignName(Context *rsc, RsObjectBase obj, const char *name, size_t name_length) {
ObjectBase *ob = static_cast<ObjectBase *>(obj);
- rsc->assignName(ob, name, len);
+ rsc->assignName(ob, name, name_length);
}
void rsi_ObjDestroy(Context *rsc, void *optr) {
@@ -1045,7 +632,7 @@ void rsi_ContextResume(Context *rsc) {
rsc->resume();
}
-void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, ANativeWindow *sur) {
+void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
rsc->setSurface(w, h, sur);
}
@@ -1058,18 +645,40 @@ void rsi_ContextDump(Context *rsc, int32_t bits) {
}
void rsi_ContextDestroyWorker(Context *rsc) {
- rsc->destroyWorkerThreadResources();;
+ rsc->destroyWorkerThreadResources();
}
+void rsi_ContextDestroy(Context *rsc) {
+ LOGV("rsContextDestroy %p", rsc);
+ rsContextDestroyWorker(rsc);
+ delete rsc;
+ LOGV("rsContextDestroy 2 %p", rsc);
}
+
+
+RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
+ size_t * receiveLen, size_t receiveLen_length,
+ uint32_t * subID, size_t subID_length) {
+ return rsc->peekMessageToClient(receiveLen, subID);
}
-void rsContextDestroy(RsContext vcon) {
- LOGV("rsContextDestroy %p", vcon);
- Context *rsc = static_cast<Context *>(vcon);
- rsContextDestroyWorker(rsc);
- delete rsc;
- LOGV("rsContextDestroy 2 %p", vcon);
+RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length,
+ size_t * receiveLen, size_t receiveLen_length,
+ uint32_t * subID, size_t subID_length) {
+ rsAssert(subID_length == sizeof(uint32_t));
+ rsAssert(receiveLen_length == sizeof(size_t));
+ return rsc->getMessageToClient(data, receiveLen, subID, data_length);
+}
+
+void rsi_ContextInitToClient(Context *rsc) {
+ rsc->initToClient();
+}
+
+void rsi_ContextDeinitToClient(Context *rsc) {
+ rsc->deinitToClient();
+}
+
+}
}
RsContext rsContextCreate(RsDevice vdev, uint32_t version) {
@@ -1089,26 +698,6 @@ RsContext rsContextCreateGL(RsDevice vdev, uint32_t version,
return rsc;
}
-RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait) {
- Context * rsc = static_cast<Context *>(vrsc);
- return rsc->peekMessageToClient(receiveLen, subID, wait);
-}
-
-RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait) {
- Context * rsc = static_cast<Context *>(vrsc);
- return rsc->getMessageToClient(data, receiveLen, subID, bufferLen, wait);
-}
-
-void rsContextInitToClient(RsContext vrsc) {
- Context * rsc = static_cast<Context *>(vrsc);
- rsc->initToClient();
-}
-
-void rsContextDeinitToClient(RsContext vrsc) {
- Context * rsc = static_cast<Context *>(vrsc);
- rsc->deinitToClient();
-}
-
// Only to be called at a3d load time, before object is visible to user
// not thread safe
void rsaGetName(RsContext con, void * obj, const char **name) {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 50f63df..309fe95 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -22,10 +22,11 @@
#include "rsAllocation.h"
#include "rsMesh.h"
-#ifndef ANDROID_RS_SERIALIZE
+#include "rs_hal.h"
+
#include "rsMutex.h"
#include "rsThreadIO.h"
-#include "rsMatrix.h"
+#include "rsMatrix4x4.h"
#include "rsDevice.h"
#include "rsScriptC.h"
#include "rsAdapter.h"
@@ -35,15 +36,11 @@
#include "rsProgramStore.h"
#include "rsProgramRaster.h"
#include "rsProgramVertex.h"
-#include "rsShaderCache.h"
-#include "rsVertexArray.h"
+#include "rsFBOCache.h"
#include "rsgApiStructs.h"
#include "rsLocklessFifo.h"
-#include <ui/egl/android_natives.h>
-#endif // ANDROID_RS_SERIALIZE
-
// ---------------------------------------------------------------------------
namespace android {
@@ -67,25 +64,23 @@ namespace renderscript {
#define CHECK_OBJ_OR_NULL(o)
#endif
-#ifndef ANDROID_RS_SERIALIZE
-
class Context {
public:
+ struct Hal {
+ void * drv;
+
+ RsdHalFunctions funcs;
+ };
+ Hal mHal;
+
static Context * createContext(Device *, const RsSurfaceConfig *sc);
+ static Context * createContextLite();
~Context();
- static pthread_key_t gThreadTLSKey;
- static uint32_t gThreadTLSKeyCount;
- static uint32_t gGLContextCount;
static pthread_mutex_t gInitMutex;
// Library mutex (for providing thread-safe calls from the runtime)
static pthread_mutex_t gLibMutex;
- struct ScriptTLSStruct {
- Context * mContext;
- Script * mScript;
- };
-
class PushState {
public:
PushState(Context *);
@@ -100,12 +95,8 @@ public:
Context *mRsc;
};
- ScriptTLSStruct *mTlsStruct;
RsSurfaceConfig mUserSurfaceConfig;
- typedef void (*WorkerCallback_t)(void *usr, uint32_t idx);
-
- //StructuredAllocationContext mStateAllocation;
ElementState mStateElement;
TypeState mStateType;
SamplerState mStateSampler;
@@ -113,11 +104,10 @@ public:
ProgramStoreState mStateFragmentStore;
ProgramRasterState mStateRaster;
ProgramVertexState mStateVertex;
- VertexArrayState mStateVertexArray;
FontState mStateFont;
ScriptCState mScriptC;
- ShaderCache mShaderCache;
+ FBOCache mFBOCache;
void swapBuffers();
void setRootScript(Script *);
@@ -140,15 +130,15 @@ public:
void pause();
void resume();
- void setSurface(uint32_t w, uint32_t h, ANativeWindow *sur);
+ void setSurface(uint32_t w, uint32_t h, RsNativeWindow sur);
void setPriority(int32_t p);
void destroyWorkerThreadResources();
void assignName(ObjectBase *obj, const char *name, uint32_t len);
void removeName(ObjectBase *obj);
- RsMessageToClientType peekMessageToClient(size_t *receiveLen, uint32_t *subID, bool wait);
- RsMessageToClientType getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait);
+ RsMessageToClientType peekMessageToClient(size_t *receiveLen, uint32_t *subID);
+ RsMessageToClientType getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen);
bool sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace) const;
uint32_t runScript(Script *s);
@@ -202,63 +192,15 @@ public:
} props;
void dumpDebug() const;
- void checkError(const char *, bool isFatal = false) const;
void setError(RsError e, const char *msg = NULL) const;
mutable const ObjectBase * mObjHead;
- bool ext_OES_texture_npot() const {return mGL.OES_texture_npot;}
- bool ext_GL_IMG_texture_npot() const {return mGL.GL_IMG_texture_npot;}
- bool ext_GL_NV_texture_npot_2D_mipmap() const {return mGL.GL_NV_texture_npot_2D_mipmap;}
- float ext_texture_max_aniso() const {return mGL.EXT_texture_max_aniso; }
- uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
- uint32_t getMaxFragmentUniformVectors() const {return mGL.mMaxFragmentUniformVectors;}
- uint32_t getMaxVertexUniformVectors() const {return mGL.mMaxVertexUniformVectors;}
- uint32_t getMaxVertexAttributes() const {return mGL.mMaxVertexAttribs;}
-
- void launchThreads(WorkerCallback_t cbk, void *data);
- uint32_t getWorkerPoolSize() const {return (uint32_t)mWorkers.mCount;}
uint32_t getDPI() const {return mDPI;}
void setDPI(uint32_t dpi) {mDPI = dpi;}
-protected:
Device *mDev;
-
- struct {
- EGLint mNumConfigs;
- EGLint mMajorVersion;
- EGLint mMinorVersion;
- EGLConfig mConfig;
- EGLContext mContext;
- EGLSurface mSurface;
- EGLSurface mSurfaceDefault;
- EGLDisplay mDisplay;
- } mEGL;
-
- struct {
- const uint8_t * mVendor;
- const uint8_t * mRenderer;
- const uint8_t * mVersion;
- const uint8_t * mExtensions;
-
- uint32_t mMajorVersion;
- uint32_t mMinorVersion;
-
- int32_t mMaxVaryingVectors;
- int32_t mMaxTextureImageUnits;
-
- int32_t mMaxFragmentTextureImageUnits;
- int32_t mMaxFragmentUniformVectors;
-
- int32_t mMaxVertexAttribs;
- int32_t mMaxVertexUniformVectors;
- int32_t mMaxVertexTextureUnits;
-
- bool OES_texture_npot;
- bool GL_IMG_texture_npot;
- bool GL_NV_texture_npot_2D_mipmap;
- float EXT_texture_max_aniso;
- } mGL;
+protected:
uint32_t mDPI;
uint32_t mWidth;
@@ -274,20 +216,6 @@ protected:
pthread_t mThreadId;
pid_t mNativeThreadId;
- struct Workers {
- volatile int mRunningCount;
- volatile int mLaunchCount;
- uint32_t mCount;
- pthread_t *mThreadId;
- pid_t *mNativeThreadId;
- Signal mCompleteSignal;
-
- Signal *mLaunchSignals;
- WorkerCallback_t mLaunchCallback;
- void *mLaunchData;
- };
- Workers mWorkers;
-
ObjectBaseRef<Script> mRootScript;
ObjectBaseRef<ProgramFragment> mFragment;
ObjectBaseRef<ProgramVertex> mVertex;
@@ -310,7 +238,8 @@ private:
static void * threadProc(void *);
static void * helperThreadProc(void *);
- ANativeWindow *mWndSurface;
+ bool mHasSurface;
+ bool mIsContextLite;
Vector<ObjectBase *> mNames;
@@ -327,39 +256,6 @@ private:
uint32_t mAverageFPS;
};
-#else
-
-class Context {
-public:
- Context() {
- mObjHead = NULL;
- }
- ~Context() {
- ObjectBase::zeroAllUserRef(this);
- }
-
- ElementState mStateElement;
- TypeState mStateType;
-
- struct {
- bool mLogTimes;
- bool mLogScripts;
- bool mLogObjects;
- bool mLogShaders;
- bool mLogShadersAttr;
- bool mLogShadersUniforms;
- bool mLogVisual;
- } props;
-
- void setError(RsError e, const char *msg = NULL) { }
-
- mutable const ObjectBase * mObjHead;
-
-protected:
-
-};
-#endif //ANDROID_RS_SERIALIZE
-
} // renderscript
} // android
#endif
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 477cb61..2b58e9e 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -347,13 +347,18 @@ RsElement rsi_ElementCreate(Context *rsc,
return (RsElement)e;
}
+
RsElement rsi_ElementCreate2(Context *rsc,
- size_t count,
const RsElement * ein,
+ size_t ein_length,
+
const char ** names,
+ size_t nameLengths_length,
const size_t * nameLengths,
- const uint32_t * arraySizes) {
- const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths, arraySizes);
+
+ const uint32_t * arraySizes,
+ size_t arraySizes_length) {
+ const Element *e = Element::create(rsc, ein_length, (const Element **)ein, names, nameLengths, arraySizes);
e->incUserRef();
return (RsElement)e;
}
diff --git a/libs/rs/rsFBOCache.cpp b/libs/rs/rsFBOCache.cpp
new file mode 100644
index 0000000..6960ef2
--- /dev/null
+++ b/libs/rs/rsFBOCache.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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 "rsFBOCache.h"
+
+#include "rsContext.h"
+#include "rsAllocation.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+FBOCache::FBOCache() {
+ mDirty = true;
+ mHal.state.colorTargetsCount = 1;
+ mHal.state.colorTargets = new ObjectBaseRef<Allocation>[mHal.state.colorTargetsCount];
+}
+
+FBOCache::~FBOCache() {
+ delete[] mHal.state.colorTargets;
+}
+
+void FBOCache::init(Context *rsc) {
+ rsc->mHal.funcs.framebuffer.init(rsc, this);
+}
+
+void FBOCache::deinit(Context *rsc) {
+ rsc->mHal.funcs.framebuffer.destroy(rsc, this);
+}
+
+void FBOCache::bindColorTarget(Context *rsc, Allocation *a, uint32_t slot) {
+ if (slot >= mHal.state.colorTargetsCount) {
+ LOGE("Invalid render target index");
+ return;
+ }
+ if (a != NULL) {
+ if (!a->getIsTexture()) {
+ LOGE("Invalid Color Target");
+ return;
+ }
+ }
+ mHal.state.colorTargets[slot].set(a);
+ mDirty = true;
+}
+
+void FBOCache::bindDepthTarget(Context *rsc, Allocation *a) {
+ if (a != NULL) {
+ if (!a->getIsRenderTarget()) {
+ LOGE("Invalid Depth Target");
+ return;
+ }
+ }
+ mHal.state.depthTarget.set(a);
+ mDirty = true;
+}
+
+void FBOCache::resetAll(Context *) {
+ for (uint32_t i = 0; i < mHal.state.colorTargetsCount; i ++) {
+ mHal.state.colorTargets[i].set(NULL);
+ }
+ mHal.state.depthTarget.set(NULL);
+ mDirty = true;
+}
+
+void FBOCache::setup(Context *rsc) {
+ if (!mDirty) {
+ return;
+ }
+
+ if (mHal.state.depthTarget.get() != NULL) {
+ mHal.state.depthTarget->syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT);
+ }
+
+ for (uint32_t i = 0; i < mHal.state.colorTargetsCount; i ++) {
+ if (mHal.state.colorTargets[i].get() != NULL) {
+ mHal.state.colorTargets[i]->syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT);
+ }
+ }
+
+ rsc->mHal.funcs.framebuffer.setActive(rsc, this);
+
+ mDirty = false;
+}
diff --git a/libs/rs/rsFBOCache.h b/libs/rs/rsFBOCache.h
new file mode 100644
index 0000000..f42e1f3
--- /dev/null
+++ b/libs/rs/rsFBOCache.h
@@ -0,0 +1,66 @@
+/*
+ * 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_FRAME_BUFFER_OBJECT_CACHE_H
+#define ANDROID_FRAME_BUFFER_OBJECT_CACHE_H
+
+#include "rsObjectBase.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Allocation;
+
+class FBOCache {
+public:
+ FBOCache();
+ ~FBOCache();
+
+ void init(Context *rsc);
+ void deinit(Context *rsc);
+
+ void bindColorTarget(Context *rsc, Allocation *a, uint32_t slot);
+ void bindDepthTarget(Context *, Allocation *a);
+ void resetAll(Context *);
+
+ void setup(Context *);
+
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ ObjectBaseRef<Allocation> *colorTargets;
+ uint32_t colorTargetsCount;
+ ObjectBaseRef<Allocation> depthTarget;
+ };
+ State state;
+ };
+ Hal mHal;
+
+protected:
+ bool mDirty;
+ void checkError(Context *);
+ void setColorAttachment(Context *rsc);
+ void setDepthAttachment(Context *rsc);
+ bool renderToFramebuffer();
+
+};
+
+} // renderscript
+} // android
+
+#endif //ANDROID_FRAME_BUFFER_OBJECT_CACHE_H
diff --git a/libs/rs/rsFifo.cpp b/libs/rs/rsFifo.cpp
new file mode 100644
index 0000000..3d5d8c4
--- /dev/null
+++ b/libs/rs/rsFifo.cpp
@@ -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.
+ */
+
+#include "rsFifoSocket.h"
+#include "utils/Timers.h"
+#include "utils/StopWatch.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+Fifo::Fifo() {
+
+}
+
+Fifo::~Fifo() {
+
+}
+
diff --git a/libs/rs/rsFifo.h b/libs/rs/rsFifo.h
new file mode 100644
index 0000000..f924b95
--- /dev/null
+++ b/libs/rs/rsFifo.h
@@ -0,0 +1,49 @@
+/*
+ * 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_RS_FIFO_H
+#define ANDROID_RS_FIFO_H
+
+
+#include "rsUtils.h"
+
+namespace android {
+namespace renderscript {
+
+
+// A simple FIFO to be used as a producer / consumer between two
+// threads. One is writer and one is reader. The common cases
+// will not require locking. It is not threadsafe for multiple
+// readers or writers by design.
+
+class Fifo {
+protected:
+ Fifo();
+ virtual ~Fifo();
+
+public:
+ void virtual writeAsync(const void *data, size_t bytes) = 0;
+ void virtual writeWaitReturn(void *ret, size_t retSize) = 0;
+ size_t virtual read(void *data, size_t bytes) = 0;
+ void virtual readReturn(const void *data, size_t bytes) = 0;
+
+ void virtual flush() = 0;
+
+};
+
+}
+}
+#endif
diff --git a/libs/rs/rsFifoSocket.cpp b/libs/rs/rsFifoSocket.cpp
new file mode 100644
index 0000000..8b8008d
--- /dev/null
+++ b/libs/rs/rsFifoSocket.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 "rsFifoSocket.h"
+#include "utils/Timers.h"
+#include "utils/StopWatch.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+FifoSocket::FifoSocket() {
+ sequence = 1;
+}
+
+FifoSocket::~FifoSocket() {
+
+}
+
+bool FifoSocket::init() {
+ int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
+ return false;
+}
+
+void FifoSocket::shutdown() {
+}
+
+void FifoSocket::writeAsync(const void *data, size_t bytes) {
+ if (bytes == 0) {
+ return;
+ }
+ //LOGE("writeAsync %p %i", data, bytes);
+ size_t ret = ::send(sv[0], data, bytes, 0);
+ //LOGE("writeAsync ret %i", ret);
+ rsAssert(ret == bytes);
+}
+
+void FifoSocket::writeWaitReturn(void *retData, size_t retBytes) {
+ //LOGE("writeWaitReturn %p %i", retData, retBytes);
+ size_t ret = ::recv(sv[0], retData, retBytes, 0);
+ //LOGE("writeWaitReturn %i", ret);
+ rsAssert(ret == retBytes);
+}
+
+size_t FifoSocket::read(void *data, size_t bytes) {
+ //LOGE("read %p %i", data, bytes);
+ size_t ret = ::recv(sv[1], data, bytes, 0);
+ rsAssert(ret == bytes);
+ //LOGE("read ret %i", ret);
+ return ret;
+}
+
+void FifoSocket::readReturn(const void *data, size_t bytes) {
+ LOGE("readReturn %p %Zu", data, bytes);
+ size_t ret = ::send(sv[1], data, bytes, 0);
+ LOGE("readReturn %Zu", ret);
+ rsAssert(ret == bytes);
+}
+
+
+void FifoSocket::flush() {
+}
+
+
diff --git a/libs/rs/rsFifoSocket.h b/libs/rs/rsFifoSocket.h
new file mode 100644
index 0000000..7df2b67
--- /dev/null
+++ b/libs/rs/rsFifoSocket.h
@@ -0,0 +1,54 @@
+/*
+ * 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_RS_FIFO_SOCKET_H
+#define ANDROID_RS_FIFO_SOCKET_H
+
+
+#include "rsFifo.h"
+
+namespace android {
+namespace renderscript {
+
+
+class FifoSocket {
+public:
+ FifoSocket();
+ virtual ~FifoSocket();
+
+ bool init();
+ void shutdown();
+
+
+
+ void virtual writeAsync(const void *data, size_t bytes);
+ void virtual writeWaitReturn(void *ret, size_t retSize);
+ size_t virtual read(void *data, size_t bytes);
+ void virtual readReturn(const void *data, size_t bytes);
+
+ void virtual flush();
+
+protected:
+ int sv[2];
+ uint32_t sequence;
+
+
+};
+
+}
+}
+
+#endif
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 01dbab8..ce674f4 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -21,14 +21,11 @@
#include "rsProgramFragment.h"
#include <cutils/properties.h>
+#ifndef ANDROID_RS_SERIALIZE
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_BITMAP_H
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
+#endif //ANDROID_RS_SERIALIZE
using namespace android;
using namespace android::renderscript;
@@ -40,6 +37,7 @@ Font::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) {
}
bool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
+#ifndef ANDROID_RS_SERIALIZE
if (mInitialized) {
LOGE("Reinitialization of fonts not supported");
return false;
@@ -70,6 +68,7 @@ bool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data
mHasKerning = FT_HAS_KERNING(mFace);
mInitialized = true;
+#endif //ANDROID_RS_SERIALIZE
return true;
}
@@ -235,6 +234,7 @@ Font::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) {
}
void Font::updateGlyphCache(CachedGlyphInfo *glyph) {
+#ifndef ANDROID_RS_SERIALIZE
FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER );
if (error) {
LOGE("Couldn't load glyph.");
@@ -275,15 +275,16 @@ void Font::updateGlyphCache(CachedGlyphInfo *glyph) {
glyph->mBitmapMinV = (float)startY / (float)cacheHeight;
glyph->mBitmapMaxU = (float)endX / (float)cacheWidth;
glyph->mBitmapMaxV = (float)endY / (float)cacheHeight;
+#endif //ANDROID_RS_SERIALIZE
}
Font::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) {
CachedGlyphInfo *newGlyph = new CachedGlyphInfo();
mCachedGlyphs.add(glyph, newGlyph);
-
+#ifndef ANDROID_RS_SERIALIZE
newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph);
newGlyph->mIsValid = false;
-
+#endif //ANDROID_RS_SERIALIZE
updateGlyphCache(newGlyph);
return newGlyph;
@@ -314,9 +315,11 @@ Font * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi
}
Font::~Font() {
+#ifndef ANDROID_RS_SERIALIZE
if (mFace) {
FT_Done_Face(mFace);
}
+#endif
for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i);
@@ -329,7 +332,9 @@ FontState::FontState() {
mMaxNumberOfQuads = 1024;
mCurrentQuadIndex = 0;
mRSC = NULL;
+#ifndef ANDROID_RS_SERIALIZE
mLibrary = NULL;
+#endif //ANDROID_RS_SERIALIZE
// Get the renderer properties
char property[PROPERTY_VALUE_MAX];
@@ -368,7 +373,7 @@ FontState::~FontState() {
rsAssert(!mActiveFonts.size());
}
-
+#ifndef ANDROID_RS_SERIALIZE
FT_Library FontState::getLib() {
if (!mLibrary) {
FT_Error error = FT_Init_FreeType(&mLibrary);
@@ -380,6 +385,8 @@ FT_Library FontState::getLib() {
return mLibrary;
}
+#endif //ANDROID_RS_SERIALIZE
+
void FontState::init(Context *rsc) {
mRSC = rsc;
@@ -398,6 +405,7 @@ void FontState::flushAllAndInvalidate() {
}
}
+#ifndef ANDROID_RS_SERIALIZE
bool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) {
// If the glyph is too tall, don't cache it
if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) {
@@ -457,7 +465,8 @@ bool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *r
// This will dirty the texture and the shader so next time
// we draw it will upload the data
- mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT);
+
+ mTextTexture->sendDirty(mRSC);
mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get());
// Some debug code
@@ -470,6 +479,7 @@ bool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *r
return true;
}
+#endif //ANDROID_RS_SERIALIZE
void FontState::initRenderState() {
String8 shaderString("varying vec2 varTex0;\n");
@@ -495,7 +505,7 @@ void FontState::initRenderState() {
tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE;
tmp[3] = RS_TEXTURE_2D;
- mFontShaderFConstant.set(new Allocation(mRSC, inputType,
+ mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType,
RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS));
ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(),
shaderString.length(), tmp, 4);
@@ -507,12 +517,13 @@ void FontState::initRenderState() {
mFontSampler.set(sampler);
mFontShaderF->bindSampler(mRSC, 0, sampler);
- ProgramStore *fontStore = new ProgramStore(mRSC);
+ ProgramStore *fontStore = new ProgramStore(mRSC, true, true, true, true,
+ false, false,
+ RS_BLEND_SRC_SRC_ALPHA,
+ RS_BLEND_DST_ONE_MINUS_SRC_ALPHA,
+ RS_DEPTH_FUNC_ALWAYS);
mFontProgramStore.set(fontStore);
- mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS);
- mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA);
- mFontProgramStore->setDitherEnable(false);
- mFontProgramStore->setDepthMask(false);
+ mFontProgramStore->init();
}
void FontState::initTextTexture() {
@@ -521,7 +532,8 @@ void FontState::initTextTexture() {
// We will allocate a texture to initially hold 32 character bitmaps
Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false);
- Allocation *cacheAlloc = new Allocation(mRSC, texType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE);
+ Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType,
+ RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE);
mTextTexture.set(cacheAlloc);
mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT);
@@ -549,7 +561,9 @@ void FontState::initVertexArrayBuffers() {
uint32_t numIndicies = mMaxNumberOfQuads * 6;
Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false);
- Allocation *indexAlloc = new Allocation(mRSC, indexType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX);
+ Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType,
+ RS_ALLOCATION_USAGE_SCRIPT |
+ RS_ALLOCATION_USAGE_GRAPHICS_VERTEX);
uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
// Four verts, two triangles , six indices per quad
@@ -566,8 +580,7 @@ void FontState::initVertexArrayBuffers() {
indexPtr[i6 + 5] = i4 + 3;
}
- indexAlloc->deferedUploadToBufferObject(mRSC);
- mIndexBuffer.set(indexAlloc);
+ indexAlloc->sendDirty(mRSC);
const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
@@ -581,10 +594,14 @@ void FontState::initVertexArrayBuffers() {
mMaxNumberOfQuads * 4,
0, 0, false, false);
- Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX);
+ Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType,
+ RS_ALLOCATION_USAGE_SCRIPT);
mTextMeshPtr = (float*)vertexAlloc->getPtr();
- mVertexArray.set(vertexAlloc);
+ mMesh.set(new Mesh(mRSC, 1, 1));
+ mMesh->setVertexBuffer(vertexAlloc, 0);
+ mMesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, 0);
+ mMesh->init();
}
// We don't want to allocate anything unless we actually draw text
@@ -624,18 +641,7 @@ void FontState::issueDrawCommand() {
return;
}
- float *vtx = (float*)mVertexArray->getPtr();
- float *tex = vtx + 3;
-
- VertexArray::Attrib attribs[2];
- attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position");
- attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0");
- VertexArray va(attribs, 2);
- va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
-
- mIndexBuffer->uploadCheck(mRSC);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
- glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
+ mMesh->renderPrimitiveRange(mRSC, 0, 0, mCurrentQuadIndex * 6);
}
void FontState::appendMeshQuad(float x1, float y1, float z1,
@@ -786,8 +792,7 @@ void FontState::deinit(Context *rsc) {
mFontShaderFConstant.clear();
- mIndexBuffer.clear();
- mVertexArray.clear();
+ mMesh.clear();
mFontShaderF.clear();
mFontSampler.clear();
@@ -800,13 +805,15 @@ void FontState::deinit(Context *rsc) {
mCacheLines.clear();
mDefault.clear();
-
+#ifndef ANDROID_RS_SERIALIZE
if (mLibrary) {
FT_Done_FreeType( mLibrary );
mLibrary = NULL;
}
+#endif //ANDROID_RS_SERIALIZE
}
+#ifndef ANDROID_RS_SERIALIZE
bool FontState::CacheTextureLine::fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) {
if ((uint32_t)bitmap->rows > mMaxHeight) {
return false;
@@ -822,11 +829,14 @@ bool FontState::CacheTextureLine::fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOri
return false;
}
+#endif //ANDROID_RS_SERIALIZE
namespace android {
namespace renderscript {
-RsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, uint32_t dpi) {
+RsFont rsi_FontCreateFromFile(Context *rsc,
+ char const *name, size_t name_length,
+ float fontSize, uint32_t dpi) {
Font *newFont = Font::create(rsc, name, fontSize, dpi);
if (newFont) {
newFont->incUserRef();
@@ -834,8 +844,11 @@ RsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, ui
return newFont;
}
-RsFont rsi_FontCreateFromMemory(Context *rsc, char const *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
- Font *newFont = Font::create(rsc, name, fontSize, dpi, data, dataLen);
+RsFont rsi_FontCreateFromMemory(Context *rsc,
+ char const *name, size_t name_length,
+ float fontSize, uint32_t dpi,
+ const void *data, size_t data_length) {
+ Font *newFont = Font::create(rsc, name, fontSize, dpi, data, data_length);
if (newFont) {
newFont->incUserRef();
}
diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h
index 91a5da9..b0e1430 100644
--- a/libs/rs/rsFont.h
+++ b/libs/rs/rsFont.h
@@ -199,8 +199,10 @@ protected:
float mWhiteThreshold;
// Free type library, we only need one copy
+#ifndef ANDROID_RS_SERIALIZE
FT_LibraryRec_ *mLibrary;
FT_LibraryRec_ *getLib();
+#endif //ANDROID_RS_SERIALIZE
Vector<Font*> mActiveFonts;
// Render state for the font
@@ -217,7 +219,9 @@ protected:
return (uint8_t*)mTextTexture->getPtr();
}
+#ifndef ANDROID_RS_SERIALIZE
bool cacheBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY);
+#endif //ANDROID_RS_SERIALIZE
const Type* getCacheTextureType() {
return mTextTexture->getType();
}
@@ -230,9 +234,7 @@ protected:
uint32_t mMaxNumberOfQuads;
void initVertexArrayBuffers();
- ObjectBaseRef<Allocation> mIndexBuffer;
- ObjectBaseRef<Allocation> mVertexArray;
-
+ ObjectBaseRef<Mesh> mMesh;
bool mInitialized;
diff --git a/libs/rs/rsHandcode.h b/libs/rs/rsHandcode.h
deleted file mode 100644
index 57da10a..0000000
--- a/libs/rs/rsHandcode.h
+++ /dev/null
@@ -1,96 +0,0 @@
-
-#define DATA_SYNC_SIZE 1024
-
-static inline void rsHCAPI_ContextFinish (RsContext rsc) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_ContextFinish);
- io->mToCore.commitSync(RS_CMD_ID_ContextFinish, size);
-}
-
-static inline void rsHCAPI_ScriptInvokeV (RsContext rsc, RsScript va, uint32_t slot, const void * data, uint32_t sizeBytes) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_ScriptInvokeV);
- if (sizeBytes < DATA_SYNC_SIZE) {
- size += (sizeBytes + 3) & ~3;
- }
- RS_CMD_ScriptInvokeV *cmd = static_cast<RS_CMD_ScriptInvokeV *>(io->mToCore.reserve(size));
- cmd->s = va;
- cmd->slot = slot;
- cmd->dataLen = sizeBytes;
- cmd->data = data;
- if (sizeBytes < DATA_SYNC_SIZE) {
- cmd->data = (void *)(cmd+1);
- memcpy(cmd+1, data, sizeBytes);
- io->mToCore.commit(RS_CMD_ID_ScriptInvokeV, size);
- } else {
- io->mToCore.commitSync(RS_CMD_ID_ScriptInvokeV, size);
- }
-}
-
-
-static inline void rsHCAPI_ScriptSetVarV (RsContext rsc, RsScript va, uint32_t slot, const void * data, uint32_t sizeBytes) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_ScriptSetVarV);
- if (sizeBytes < DATA_SYNC_SIZE) {
- size += (sizeBytes + 3) & ~3;
- }
- RS_CMD_ScriptSetVarV *cmd = static_cast<RS_CMD_ScriptSetVarV *>(io->mToCore.reserve(size));
- cmd->s = va;
- cmd->slot = slot;
- cmd->dataLen = sizeBytes;
- cmd->data = data;
- if (sizeBytes < DATA_SYNC_SIZE) {
- cmd->data = (void *)(cmd+1);
- memcpy(cmd+1, data, sizeBytes);
- io->mToCore.commit(RS_CMD_ID_ScriptSetVarV, size);
- } else {
- io->mToCore.commitSync(RS_CMD_ID_ScriptSetVarV, size);
- }
-}
-
-static inline void rsHCAPI_Allocation1DData (RsContext rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
- uint32_t count, const void * data, uint32_t sizeBytes) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_Allocation1DData);
- if (sizeBytes < DATA_SYNC_SIZE) {
- size += (sizeBytes + 3) & ~3;
- }
- RS_CMD_Allocation1DData *cmd = static_cast<RS_CMD_Allocation1DData *>(io->mToCore.reserve(size));
- cmd->va = va;
- cmd->xoff = xoff;
- cmd->lod = lod;
- cmd->count = count;
- cmd->data = data;
- cmd->bytes = sizeBytes;
- if (sizeBytes < DATA_SYNC_SIZE) {
- cmd->data = (void *)(cmd+1);
- memcpy(cmd+1, data, sizeBytes);
- io->mToCore.commit(RS_CMD_ID_Allocation1DData, size);
- } else {
- io->mToCore.commitSync(RS_CMD_ID_Allocation1DData, size);
- }
-}
-
-static inline void rsHCAPI_Allocation1DElementData (RsContext rsc, RsAllocation va, uint32_t x, uint32_t lod,
- const void * data, uint32_t comp_offset, uint32_t sizeBytes) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_Allocation1DElementData);
- if (sizeBytes < DATA_SYNC_SIZE) {
- size += (sizeBytes + 3) & ~3;
- }
- RS_CMD_Allocation1DElementData *cmd = static_cast<RS_CMD_Allocation1DElementData *>(io->mToCore.reserve(size));
- cmd->va = va;
- cmd->x = x;
- cmd->lod = lod;
- cmd->data = data;
- cmd->comp_offset = comp_offset;
- cmd->bytes = sizeBytes;
- if (sizeBytes < DATA_SYNC_SIZE) {
- cmd->data = (void *)(cmd+1);
- memcpy(cmd+1, data, sizeBytes);
- io->mToCore.commit(RS_CMD_ID_Allocation1DElementData, size);
- } else {
- io->mToCore.commitSync(RS_CMD_ID_Allocation1DElementData, size);
- }
-}
-
diff --git a/libs/rs/rsMatrix.cpp b/libs/rs/rsMatrix.cpp
deleted file mode 100644
index ca41886..0000000
--- a/libs/rs/rsMatrix.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2009 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 "rsMatrix.h"
-
-#include "stdlib.h"
-#include "string.h"
-#include "math.h"
-
-using namespace android;
-using namespace android::renderscript;
-
-void Matrix::loadIdentity() {
- set(0, 0, 1);
- set(1, 0, 0);
- set(2, 0, 0);
- set(3, 0, 0);
-
- set(0, 1, 0);
- set(1, 1, 1);
- set(2, 1, 0);
- set(3, 1, 0);
-
- set(0, 2, 0);
- set(1, 2, 0);
- set(2, 2, 1);
- set(3, 2, 0);
-
- set(0, 3, 0);
- set(1, 3, 0);
- set(2, 3, 0);
- set(3, 3, 1);
-}
-
-void Matrix::load(const float *v) {
- memcpy(m, v, sizeof(m));
-}
-
-void Matrix::load(const Matrix *v) {
- memcpy(m, v->m, sizeof(m));
-}
-
-void Matrix::loadRotate(float rot, float x, float y, float z) {
- float c, s;
- m[3] = 0;
- m[7] = 0;
- m[11]= 0;
- m[12]= 0;
- m[13]= 0;
- m[14]= 0;
- m[15]= 1;
- rot *= float(M_PI / 180.0f);
- c = cosf(rot);
- s = sinf(rot);
-
- const float len = sqrtf(x*x + y*y + z*z);
- if (len != 1) {
- const float recipLen = 1.f / len;
- x *= recipLen;
- y *= recipLen;
- z *= recipLen;
- }
- const float nc = 1.0f - c;
- const float xy = x * y;
- const float yz = y * z;
- const float zx = z * x;
- const float xs = x * s;
- const float ys = y * s;
- const float zs = z * s;
- m[ 0] = x*x*nc + c;
- m[ 4] = xy*nc - zs;
- m[ 8] = zx*nc + ys;
- m[ 1] = xy*nc + zs;
- m[ 5] = y*y*nc + c;
- m[ 9] = yz*nc - xs;
- m[ 2] = zx*nc - ys;
- m[ 6] = yz*nc + xs;
- m[10] = z*z*nc + c;
-}
-
-void Matrix::loadScale(float x, float y, float z) {
- loadIdentity();
- m[0] = x;
- m[5] = y;
- m[10] = z;
-}
-
-void Matrix::loadTranslate(float x, float y, float z) {
- loadIdentity();
- m[12] = x;
- m[13] = y;
- m[14] = z;
-}
-
-void Matrix::loadMultiply(const Matrix *lhs, const Matrix *rhs) {
- for (int i=0 ; i<4 ; i++) {
- float ri0 = 0;
- float ri1 = 0;
- float ri2 = 0;
- float ri3 = 0;
- for (int j=0 ; j<4 ; j++) {
- const float rhs_ij = rhs->get(i,j);
- ri0 += lhs->get(j,0) * rhs_ij;
- ri1 += lhs->get(j,1) * rhs_ij;
- ri2 += lhs->get(j,2) * rhs_ij;
- ri3 += lhs->get(j,3) * rhs_ij;
- }
- set(i,0, ri0);
- set(i,1, ri1);
- set(i,2, ri2);
- set(i,3, ri3);
- }
-}
-
-void Matrix::loadOrtho(float l, float r, float b, float t, float n, float f) {
- loadIdentity();
- m[0] = 2 / (r - l);
- m[5] = 2 / (t - b);
- m[10]= -2 / (f - n);
- m[12]= -(r + l) / (r - l);
- m[13]= -(t + b) / (t - b);
- m[14]= -(f + n) / (f - n);
-}
-
-void Matrix::loadFrustum(float l, float r, float b, float t, float n, float f) {
- loadIdentity();
- m[0] = 2 * n / (r - l);
- m[5] = 2 * n / (t - b);
- m[8] = (r + l) / (r - l);
- m[9] = (t + b) / (t - b);
- m[10]= -(f + n) / (f - n);
- m[11]= -1;
- m[14]= -2*f*n / (f - n);
- m[15]= 0;
-}
-
-void Matrix::vectorMultiply(float *out, const float *in) const {
- out[0] = (m[0] * in[0]) + (m[4] * in[1]) + (m[8] * in[2]) + m[12];
- out[1] = (m[1] * in[0]) + (m[5] * in[1]) + (m[9] * in[2]) + m[13];
- out[2] = (m[2] * in[0]) + (m[6] * in[1]) + (m[10] * in[2]) + m[14];
- out[3] = (m[3] * in[0]) + (m[7] * in[1]) + (m[11] * in[2]) + m[15];
-}
diff --git a/libs/rs/rsMatrix2x2.cpp b/libs/rs/rsMatrix2x2.cpp
new file mode 100644
index 0000000..622113c
--- /dev/null
+++ b/libs/rs/rsMatrix2x2.cpp
@@ -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.
+ */
+
+#include "rsMatrix2x2.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix4x4.h"
+
+#include "stdlib.h"
+#include "string.h"
+#include "math.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+void Matrix2x2::loadIdentity() {
+ m[0] = 1.f;
+ m[1] = 0.f;
+ m[2] = 0.f;
+ m[3] = 1.f;
+}
+
+void Matrix2x2::load(const float *v) {
+ memcpy(m, v, sizeof(m));
+}
+
+void Matrix2x2::load(const rs_matrix2x2 *v) {
+ memcpy(m, v->m, sizeof(m));
+}
+
+void Matrix2x2::loadMultiply(const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs) {
+ for (int i=0 ; i<2 ; i++) {
+ float ri0 = 0;
+ float ri1 = 0;
+ for (int j=0 ; j<2 ; j++) {
+ const float rhs_ij = ((const Matrix2x2 *)rhs)->get(i, j);
+ ri0 += ((const Matrix2x2 *)lhs)->get(j, 0) * rhs_ij;
+ ri1 += ((const Matrix2x2 *)lhs)->get(j, 1) * rhs_ij;
+ }
+ set(i, 0, ri0);
+ set(i, 1, ri1);
+ }
+}
+
+void Matrix2x2::transpose() {
+ float temp = m[1];
+ m[1] = m[2];
+ m[2] = temp;
+}
+
diff --git a/libs/rs/rsMatrix2x2.h b/libs/rs/rsMatrix2x2.h
new file mode 100644
index 0000000..4dcb84a
--- /dev/null
+++ b/libs/rs/rsMatrix2x2.h
@@ -0,0 +1,62 @@
+/*
+ * 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_RS_MATRIX_2x2_H
+#define ANDROID_RS_MATRIX_2x2_H
+
+#include "rsType.h"
+
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+struct Matrix2x2 : public rs_matrix2x2 {
+ inline float get(uint32_t row, uint32_t col) const {
+ return m[row*2 + col];
+ }
+
+ inline void set(uint32_t row, uint32_t col, float v) {
+ m[row*2 + col] = v;
+ }
+
+ void loadIdentity();
+ void load(const float *);
+ void load(const rs_matrix2x2 *);
+
+ void loadMultiply(const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs);
+
+ void transpose();
+
+ void multiply(const rs_matrix2x2 *rhs) {
+ Matrix2x2 tmp;
+ tmp.loadMultiply(this, rhs);
+ load(&tmp);
+ }
+};
+
+}
+}
+
+
+
+
+#endif
+
+
+
+
+
diff --git a/libs/rs/rsMatrix3x3.cpp b/libs/rs/rsMatrix3x3.cpp
new file mode 100644
index 0000000..3f9a2d1
--- /dev/null
+++ b/libs/rs/rsMatrix3x3.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 "rsMatrix2x2.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix4x4.h"
+
+#include "stdlib.h"
+#include "string.h"
+#include "math.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+void Matrix3x3::loadIdentity() {
+ m[0] = 1.f;
+ m[1] = 0.f;
+ m[2] = 0.f;
+ m[3] = 0.f;
+ m[4] = 1.f;
+ m[5] = 0.f;
+ m[6] = 0.f;
+ m[7] = 0.f;
+ m[8] = 1.f;
+}
+
+void Matrix3x3::load(const float *v) {
+ memcpy(m, v, sizeof(m));
+}
+
+void Matrix3x3::load(const rs_matrix3x3 *v) {
+ memcpy(m, v->m, sizeof(m));
+}
+
+void Matrix3x3::loadMultiply(const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs) {
+ for (int i=0 ; i<3 ; i++) {
+ float ri0 = 0;
+ float ri1 = 0;
+ float ri2 = 0;
+ for (int j=0 ; j<3 ; j++) {
+ const float rhs_ij = ((const Matrix3x3 *)rhs)->get(i, j);
+ ri0 += ((const Matrix3x3 *)lhs)->get(j, 0) * rhs_ij;
+ ri1 += ((const Matrix3x3 *)lhs)->get(j, 1) * rhs_ij;
+ ri2 += ((const Matrix3x3 *)lhs)->get(j, 2) * rhs_ij;
+ }
+ set(i, 0, ri0);
+ set(i, 1, ri1);
+ set(i, 2, ri2);
+ }
+}
+
+void Matrix3x3::transpose() {
+ int i, j;
+ float temp;
+ for (i = 0; i < 2; ++i) {
+ for (j = i + 1; j < 3; ++j) {
+ temp = get(i, j);
+ set(i, j, get(j, i));
+ set(j, i, temp);
+ }
+ }
+}
+
diff --git a/libs/rs/rsMatrix3x3.h b/libs/rs/rsMatrix3x3.h
new file mode 100644
index 0000000..f96d270
--- /dev/null
+++ b/libs/rs/rsMatrix3x3.h
@@ -0,0 +1,62 @@
+/*
+ * 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_RS_MATRIX_3x3_H
+#define ANDROID_RS_MATRIX_3x3_H
+
+#include "rsType.h"
+
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+struct Matrix3x3 : public rs_matrix3x3 {
+ inline float get(uint32_t row, uint32_t col) const {
+ return m[row*3 + col];
+ }
+
+ inline void set(uint32_t row, uint32_t col, float v) {
+ m[row*3 + col] = v;
+ }
+
+ void loadIdentity();
+ void load(const float *);
+ void load(const rs_matrix3x3 *);
+
+ void loadMultiply(const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs);
+
+ void transpose();
+
+ void multiply(const rs_matrix3x3 *rhs) {
+ Matrix3x3 tmp;
+ tmp.loadMultiply(this, rhs);
+ load(&tmp);
+ }
+};
+
+}
+}
+
+
+
+
+#endif
+
+
+
+
+
diff --git a/libs/rs/rsMatrix4x4.cpp b/libs/rs/rsMatrix4x4.cpp
new file mode 100644
index 0000000..f34af47
--- /dev/null
+++ b/libs/rs/rsMatrix4x4.cpp
@@ -0,0 +1,314 @@
+/*
+ * 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 "rsMatrix2x2.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix4x4.h"
+
+#include "stdlib.h"
+#include "string.h"
+#include "math.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+//////////////////////////////////////////////////////////////////////////////
+// Heavy math functions
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+// Returns true if the matrix was successfully inversed
+bool Matrix4x4::inverse() {
+ rs_matrix4x4 result;
+
+ int i, j;
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < 4; ++j) {
+ // computeCofactor for int i, int j
+ int c0 = (i+1) % 4;
+ int c1 = (i+2) % 4;
+ int c2 = (i+3) % 4;
+ int r0 = (j+1) % 4;
+ int r1 = (j+2) % 4;
+ int r2 = (j+3) % 4;
+
+ float minor =
+ (m[c0 + 4*r0] * (m[c1 + 4*r1] * m[c2 + 4*r2] - m[c1 + 4*r2] * m[c2 + 4*r1]))
+ - (m[c0 + 4*r1] * (m[c1 + 4*r0] * m[c2 + 4*r2] - m[c1 + 4*r2] * m[c2 + 4*r0]))
+ + (m[c0 + 4*r2] * (m[c1 + 4*r0] * m[c2 + 4*r1] - m[c1 + 4*r1] * m[c2 + 4*r0]));
+
+ float cofactor = (i+j) & 1 ? -minor : minor;
+
+ result.m[4*i + j] = cofactor;
+ }
+ }
+
+ // Dot product of 0th column of source and 0th row of result
+ float det = m[0]*result.m[0] + m[4]*result.m[1] +
+ m[8]*result.m[2] + m[12]*result.m[3];
+
+ if (fabs(det) < 1e-6) {
+ return false;
+ }
+
+ det = 1.0f / det;
+ for (i = 0; i < 16; ++i) {
+ m[i] = result.m[i] * det;
+ }
+
+ return true;
+}
+
+// Returns true if the matrix was successfully inversed
+bool Matrix4x4::inverseTranspose() {
+ rs_matrix4x4 result;
+
+ int i, j;
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < 4; ++j) {
+ // computeCofactor for int i, int j
+ int c0 = (i+1) % 4;
+ int c1 = (i+2) % 4;
+ int c2 = (i+3) % 4;
+ int r0 = (j+1) % 4;
+ int r1 = (j+2) % 4;
+ int r2 = (j+3) % 4;
+
+ float minor = (m[c0 + 4*r0] * (m[c1 + 4*r1] * m[c2 + 4*r2] - m[c1 + 4*r2] * m[c2 + 4*r1]))
+ - (m[c0 + 4*r1] * (m[c1 + 4*r0] * m[c2 + 4*r2] - m[c1 + 4*r2] * m[c2 + 4*r0]))
+ + (m[c0 + 4*r2] * (m[c1 + 4*r0] * m[c2 + 4*r1] - m[c1 + 4*r1] * m[c2 + 4*r0]));
+
+ float cofactor = (i+j) & 1 ? -minor : minor;
+
+ result.m[4*j + i] = cofactor;
+ }
+ }
+
+ // Dot product of 0th column of source and 0th column of result
+ float det = m[0]*result.m[0] + m[4]*result.m[4] +
+ m[8]*result.m[8] + m[12]*result.m[12];
+
+ if (fabs(det) < 1e-6) {
+ return false;
+ }
+
+ det = 1.0f / det;
+ for (i = 0; i < 16; ++i) {
+ m[i] = result.m[i] * det;
+ }
+
+ return true;
+}
+
+void Matrix4x4::transpose() {
+ int i, j;
+ float temp;
+ for (i = 0; i < 3; ++i) {
+ for (j = i + 1; j < 4; ++j) {
+ temp = m[i*4 + j];
+ m[i*4 + j] = m[j*4 + i];
+ m[j*4 + i] = temp;
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////
+
+void Matrix4x4::loadIdentity() {
+ m[0] = 1.f;
+ m[1] = 0.f;
+ m[2] = 0.f;
+ m[3] = 0.f;
+ m[4] = 0.f;
+ m[5] = 1.f;
+ m[6] = 0.f;
+ m[7] = 0.f;
+ m[8] = 0.f;
+ m[9] = 0.f;
+ m[10] = 1.f;
+ m[11] = 0.f;
+ m[12] = 0.f;
+ m[13] = 0.f;
+ m[14] = 0.f;
+ m[15] = 1.f;
+}
+
+void Matrix4x4::load(const float *v) {
+ memcpy(m, v, sizeof(m));
+}
+
+void Matrix4x4::load(const rs_matrix4x4 *v) {
+ memcpy(m, v->m, sizeof(m));
+}
+
+void Matrix4x4::load(const rs_matrix3x3 *v) {
+ m[0] = v->m[0];
+ m[1] = v->m[1];
+ m[2] = v->m[2];
+ m[3] = 0.f;
+ m[4] = v->m[3];
+ m[5] = v->m[4];
+ m[6] = v->m[5];
+ m[7] = 0.f;
+ m[8] = v->m[6];
+ m[9] = v->m[7];
+ m[10] = v->m[8];
+ m[11] = 0.f;
+ m[12] = 0.f;
+ m[13] = 0.f;
+ m[14] = 0.f;
+ m[15] = 1.f;
+}
+
+void Matrix4x4::load(const rs_matrix2x2 *v) {
+ m[0] = v->m[0];
+ m[1] = v->m[1];
+ m[2] = 0.f;
+ m[3] = 0.f;
+ m[4] = v->m[2];
+ m[5] = v->m[3];
+ m[6] = 0.f;
+ m[7] = 0.f;
+ m[8] = 0.f;
+ m[9] = 0.f;
+ m[10] = 1.f;
+ m[11] = 0.f;
+ m[12] = 0.f;
+ m[13] = 0.f;
+ m[14] = 0.f;
+ m[15] = 1.f;
+}
+
+
+void Matrix4x4::loadRotate(float rot, float x, float y, float z) {
+ float c, s;
+ m[3] = 0;
+ m[7] = 0;
+ m[11]= 0;
+ m[12]= 0;
+ m[13]= 0;
+ m[14]= 0;
+ m[15]= 1;
+ rot *= float(M_PI / 180.0f);
+ c = cosf(rot);
+ s = sinf(rot);
+
+ const float len = x*x + y*y + z*z;
+ if (len != 1) {
+ const float recipLen = 1.f / sqrtf(len);
+ x *= recipLen;
+ y *= recipLen;
+ z *= recipLen;
+ }
+ const float nc = 1.0f - c;
+ const float xy = x * y;
+ const float yz = y * z;
+ const float zx = z * x;
+ const float xs = x * s;
+ const float ys = y * s;
+ const float zs = z * s;
+ m[ 0] = x*x*nc + c;
+ m[ 4] = xy*nc - zs;
+ m[ 8] = zx*nc + ys;
+ m[ 1] = xy*nc + zs;
+ m[ 5] = y*y*nc + c;
+ m[ 9] = yz*nc - xs;
+ m[ 2] = zx*nc - ys;
+ m[ 6] = yz*nc + xs;
+ m[10] = z*z*nc + c;
+}
+
+void Matrix4x4::loadScale(float x, float y, float z) {
+ loadIdentity();
+ set(0, 0, x);
+ set(1, 1, y);
+ set(2, 2, z);
+}
+
+void Matrix4x4::loadTranslate(float x, float y, float z) {
+ loadIdentity();
+ m[12] = x;
+ m[13] = y;
+ m[14] = z;
+}
+
+void Matrix4x4::loadMultiply(const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs) {
+ for (int i=0 ; i<4 ; i++) {
+ float ri0 = 0;
+ float ri1 = 0;
+ float ri2 = 0;
+ float ri3 = 0;
+ for (int j=0 ; j<4 ; j++) {
+ const float rhs_ij = ((const Matrix4x4 *)rhs)->get(i,j);
+ ri0 += ((const Matrix4x4 *)lhs)->get(j,0) * rhs_ij;
+ ri1 += ((const Matrix4x4 *)lhs)->get(j,1) * rhs_ij;
+ ri2 += ((const Matrix4x4 *)lhs)->get(j,2) * rhs_ij;
+ ri3 += ((const Matrix4x4 *)lhs)->get(j,3) * rhs_ij;
+ }
+ set(i,0, ri0);
+ set(i,1, ri1);
+ set(i,2, ri2);
+ set(i,3, ri3);
+ }
+}
+
+void Matrix4x4::loadOrtho(float left, float right, float bottom, float top, float near, float far) {
+ loadIdentity();
+ m[0] = 2.f / (right - left);
+ m[5] = 2.f / (top - bottom);
+ m[10]= -2.f / (far - near);
+ m[12]= -(right + left) / (right - left);
+ m[13]= -(top + bottom) / (top - bottom);
+ m[14]= -(far + near) / (far - near);
+}
+
+void Matrix4x4::loadFrustum(float left, float right, float bottom, float top, float near, float far) {
+ loadIdentity();
+ m[0] = 2.f * near / (right - left);
+ m[5] = 2.f * near / (top - bottom);
+ m[8] = (right + left) / (right - left);
+ m[9] = (top + bottom) / (top - bottom);
+ m[10]= -(far + near) / (far - near);
+ m[11]= -1.f;
+ m[14]= -2.f * far * near / (far - near);
+ m[15]= 0.f;
+}
+
+void Matrix4x4::loadPerspective(float fovy, float aspect, float near, float far) {
+ float top = near * tan((float) (fovy * M_PI / 360.0f));
+ float bottom = -top;
+ float left = bottom * aspect;
+ float right = top * aspect;
+ loadFrustum(left, right, bottom, top, near, far);
+}
+
+void Matrix4x4::vectorMultiply(float *out, const float *in) const {
+ out[0] = (m[0] * in[0]) + (m[4] * in[1]) + (m[8] * in[2]) + m[12];
+ out[1] = (m[1] * in[0]) + (m[5] * in[1]) + (m[9] * in[2]) + m[13];
+ out[2] = (m[2] * in[0]) + (m[6] * in[1]) + (m[10] * in[2]) + m[14];
+ out[3] = (m[3] * in[0]) + (m[7] * in[1]) + (m[11] * in[2]) + m[15];
+}
+
+void Matrix4x4::logv(const char *s) const {
+ LOGV("%s {%f, %f, %f, %f", s, m[0], m[4], m[8], m[12]);
+ LOGV("%s %f, %f, %f, %f", s, m[1], m[5], m[9], m[13]);
+ LOGV("%s %f, %f, %f, %f", s, m[2], m[6], m[10], m[14]);
+ LOGV("%s %f, %f, %f, %f}", s, m[3], m[7], m[11], m[15]);
+}
diff --git a/libs/rs/rsMatrix.h b/libs/rs/rsMatrix4x4.h
index 4130b8e..d30184f 100644
--- a/libs/rs/rsMatrix.h
+++ b/libs/rs/rsMatrix4x4.h
@@ -14,57 +14,66 @@
* limitations under the License.
*/
-#ifndef ANDROID_RS_MATRIX_H
-#define ANDROID_RS_MATRIX_H
+#ifndef ANDROID_RS_MATRIX_4x4_H
+#define ANDROID_RS_MATRIX_4x4_H
+#include "rsType.h"
// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
-struct Matrix {
- float m[16];
-
- inline float get(int i, int j) const {
- return m[i*4 + j];
+struct Matrix4x4 : public rs_matrix4x4 {
+ float get(uint32_t row, uint32_t col) const {
+ return m[row*4 + col];
}
- inline void set(int i, int j, float v) {
- m[i*4 + j] = v;
+ void set(uint32_t row, uint32_t col, float v) {
+ m[row*4 + col] = v;
}
void loadIdentity();
void load(const float *);
- void load(const Matrix *);
+ void load(const rs_matrix4x4 *);
+ void load(const rs_matrix3x3 *);
+ void load(const rs_matrix2x2 *);
void loadRotate(float rot, float x, float y, float z);
void loadScale(float x, float y, float z);
void loadTranslate(float x, float y, float z);
- void loadMultiply(const Matrix *lhs, const Matrix *rhs);
+ void loadMultiply(const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs);
void loadOrtho(float l, float r, float b, float t, float n, float f);
void loadFrustum(float l, float r, float b, float t, float n, float f);
+ void loadPerspective(float fovy, float aspect, float near, float far);
void vectorMultiply(float *v4out, const float *v3in) const;
- void multiply(const Matrix *rhs) {
- Matrix tmp;
+ bool inverse();
+ bool inverseTranspose();
+ void transpose();
+
+ void logv(const char *s) const;
+
+
+ void multiply(const rs_matrix4x4 *rhs) {
+ Matrix4x4 tmp;
tmp.loadMultiply(this, rhs);
load(&tmp);
}
void rotate(float rot, float x, float y, float z) {
- Matrix tmp;
+ Matrix4x4 tmp;
tmp.loadRotate(rot, x, y, z);
multiply(&tmp);
}
void scale(float x, float y, float z) {
- Matrix tmp;
+ Matrix4x4 tmp;
tmp.loadScale(x, y, z);
multiply(&tmp);
}
void translate(float x, float y, float z) {
- Matrix tmp;
+ Matrix4x4 tmp;
tmp.loadTranslate(x, y, z);
multiply(&tmp);
}
diff --git a/libs/rs/rsMesh.cpp b/libs/rs/rsMesh.cpp
index 76fe62d..359d09f 100644
--- a/libs/rs/rsMesh.cpp
+++ b/libs/rs/rsMesh.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -15,46 +15,53 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES2/gl2.h>
-#include <GLES/glext.h>
-#endif
using namespace android;
using namespace android::renderscript;
Mesh::Mesh(Context *rsc) : ObjectBase(rsc) {
- mPrimitives = NULL;
- mPrimitivesCount = 0;
- mVertexBuffers = NULL;
- mVertexBufferCount = 0;
-
-#ifndef ANDROID_RS_SERIALIZE
- mAttribs = NULL;
- mAttribAllocationIndex = NULL;
+ mHal.drv = NULL;
+ mHal.state.primitives = NULL;
+ mHal.state.primitivesCount = 0;
+ mHal.state.vertexBuffers = NULL;
+ mHal.state.vertexBuffersCount = 0;
+ mInitialized = false;
+}
- mAttribCount = 0;
-#endif
+Mesh::Mesh(Context *rsc,
+ uint32_t vertexBuffersCount,
+ uint32_t primitivesCount) : ObjectBase(rsc) {
+ mHal.drv = NULL;
+ mHal.state.primitivesCount = primitivesCount;
+ mHal.state.primitives = new Primitive_t *[mHal.state.primitivesCount];
+ for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) {
+ mHal.state.primitives[i] = new Primitive_t;
+ }
+ mHal.state.vertexBuffersCount = vertexBuffersCount;
+ mHal.state.vertexBuffers = new ObjectBaseRef<Allocation>[mHal.state.vertexBuffersCount];
}
Mesh::~Mesh() {
- if (mVertexBuffers) {
- delete[] mVertexBuffers;
+#ifndef ANDROID_RS_SERIALIZE
+ mRSC->mHal.funcs.mesh.destroy(mRSC, this);
+#endif
+
+ if (mHal.state.vertexBuffers) {
+ delete[] mHal.state.vertexBuffers;
}
- if (mPrimitives) {
- for (uint32_t i = 0; i < mPrimitivesCount; i ++) {
- delete mPrimitives[i];
+ if (mHal.state.primitives) {
+ for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) {
+ mHal.state.primitives[i]->mIndexBuffer.clear();
+ delete mHal.state.primitives[i];
}
- delete[] mPrimitives;
+ delete[] mHal.state.primitives;
}
+}
+void Mesh::init() {
#ifndef ANDROID_RS_SERIALIZE
- if (mAttribs) {
- delete[] mAttribs;
- delete[] mAttribAllocationIndex;
- }
+ mRSC->mHal.funcs.mesh.init(mRSC, this);
#endif
}
@@ -66,15 +73,15 @@ void Mesh::serialize(OStream *stream) const {
stream->addString(&name);
// Store number of vertex streams
- stream->addU32(mVertexBufferCount);
- for (uint32_t vCount = 0; vCount < mVertexBufferCount; vCount ++) {
- mVertexBuffers[vCount]->serialize(stream);
+ stream->addU32(mHal.state.vertexBuffersCount);
+ for (uint32_t vCount = 0; vCount < mHal.state.vertexBuffersCount; vCount ++) {
+ mHal.state.vertexBuffers[vCount]->serialize(stream);
}
- stream->addU32(mPrimitivesCount);
+ stream->addU32(mHal.state.primitivesCount);
// Store the primitives
- for (uint32_t pCount = 0; pCount < mPrimitivesCount; pCount ++) {
- Primitive_t * prim = mPrimitives[pCount];
+ for (uint32_t pCount = 0; pCount < mHal.state.primitivesCount; pCount ++) {
+ Primitive_t * prim = mHal.state.primitives[pCount];
stream->addU8((uint8_t)prim->mPrimitive);
@@ -95,213 +102,106 @@ Mesh *Mesh::createFromStream(Context *rsc, IStream *stream) {
return NULL;
}
- Mesh * mesh = new Mesh(rsc);
-
String8 name;
stream->loadString(&name);
- mesh->setName(name.string(), name.size());
- mesh->mVertexBufferCount = stream->loadU32();
- if (mesh->mVertexBufferCount) {
- mesh->mVertexBuffers = new ObjectBaseRef<Allocation>[mesh->mVertexBufferCount];
+ uint32_t vertexBuffersCount = stream->loadU32();
+ ObjectBaseRef<Allocation> *vertexBuffers = NULL;
+ if (vertexBuffersCount) {
+ vertexBuffers = new ObjectBaseRef<Allocation>[vertexBuffersCount];
- for (uint32_t vCount = 0; vCount < mesh->mVertexBufferCount; vCount ++) {
+ for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) {
Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream);
- mesh->mVertexBuffers[vCount].set(vertexAlloc);
+ vertexBuffers[vCount].set(vertexAlloc);
}
}
- mesh->mPrimitivesCount = stream->loadU32();
- if (mesh->mPrimitivesCount) {
- mesh->mPrimitives = new Primitive_t *[mesh->mPrimitivesCount];
+ uint32_t primitivesCount = stream->loadU32();
+ ObjectBaseRef<Allocation> *indexBuffers = NULL;
+ RsPrimitive *primitives = NULL;
+ if (primitivesCount) {
+ indexBuffers = new ObjectBaseRef<Allocation>[primitivesCount];
+ primitives = new RsPrimitive[primitivesCount];
// load all primitives
- for (uint32_t pCount = 0; pCount < mesh->mPrimitivesCount; pCount ++) {
- Primitive_t * prim = new Primitive_t;
- mesh->mPrimitives[pCount] = prim;
-
- prim->mPrimitive = (RsPrimitive)stream->loadU8();
+ for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) {
+ primitives[pCount] = (RsPrimitive)stream->loadU8();
// Check to see if the index buffer was stored
uint32_t isIndexPresent = stream->loadU32();
if (isIndexPresent) {
Allocation *indexAlloc = Allocation::createFromStream(rsc, stream);
- prim->mIndexBuffer.set(indexAlloc);
+ indexBuffers[pCount].set(indexAlloc);
}
}
}
-#ifndef ANDROID_RS_SERIALIZE
- mesh->updateGLPrimitives();
- mesh->initVertexAttribs();
- mesh->uploadAll(rsc);
-#endif
- return mesh;
-}
-
-#ifndef ANDROID_RS_SERIALIZE
-
-bool Mesh::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;
+ Mesh *mesh = new Mesh(rsc, vertexBuffersCount, primitivesCount);
+ mesh->setName(name.string(), name.size());
+ for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) {
+ mesh->setVertexBuffer(vertexBuffers[vCount].get(), vCount);
}
-
- return true;
-}
-
-void Mesh::initVertexAttribs() {
- // Count the number of gl attrs to initialize
- mAttribCount = 0;
- for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
- const Element *elem = mVertexBuffers[ct]->getType()->getElement();
- for (uint32_t ct=0; ct < elem->getFieldCount(); ct++) {
- if (isValidGLComponent(elem, ct)) {
- mAttribCount ++;
- }
- }
+ for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) {
+ mesh->setPrimitive(indexBuffers[pCount].get(), primitives[pCount], pCount);
}
- if (mAttribs) {
- delete [] mAttribs;
- delete [] mAttribAllocationIndex;
- mAttribs = NULL;
- mAttribAllocationIndex = NULL;
+ // Cleanup
+ if (vertexBuffersCount) {
+ delete[] vertexBuffers;
}
- if (!mAttribCount) {
- return;
+ if (primitivesCount) {
+ delete[] indexBuffers;
+ delete[] primitives;
}
- mAttribs = new VertexArray::Attrib[mAttribCount];
- mAttribAllocationIndex = new uint32_t[mAttribCount];
-
- uint32_t userNum = 0;
- for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
- const Element *elem = mVertexBuffers[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 = c.getGLType();
- 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 ++;
- }
- }
+#ifndef ANDROID_RS_SERIALIZE
+ mesh->init();
+ mesh->uploadAll(rsc);
+#endif
+ return mesh;
}
void Mesh::render(Context *rsc) const {
- for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) {
+ for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
renderPrimitive(rsc, ct);
}
}
void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const {
- if (primIndex >= mPrimitivesCount) {
+ if (primIndex >= mHal.state.primitivesCount) {
LOGE("Invalid primitive index");
return;
}
- Primitive_t *prim = mPrimitives[primIndex];
+ Primitive_t *prim = mHal.state.primitives[primIndex];
if (prim->mIndexBuffer.get()) {
renderPrimitiveRange(rsc, primIndex, 0, prim->mIndexBuffer->getType()->getDimX());
return;
}
- renderPrimitiveRange(rsc, primIndex, 0, mVertexBuffers[0]->getType()->getDimX());
+ renderPrimitiveRange(rsc, primIndex, 0, mHal.state.vertexBuffers[0]->getType()->getDimX());
}
void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
- if (len < 1 || primIndex >= mPrimitivesCount || mAttribCount == 0) {
+ if (len < 1 || primIndex >= mHal.state.primitivesCount) {
LOGE("Invalid mesh or parameters");
return;
}
- rsc->checkError("Mesh::renderPrimitiveRange 1");
- for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
- mVertexBuffers[ct]->uploadCheck(rsc);
- }
- // 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 = mVertexBuffers[allocIndex].get();
- if (alloc->getIsBufferObject()) {
- mAttribs[ct].buffer = alloc->getBufferObjectID();
- mAttribs[ct].ptr = NULL;
- } else {
- mAttribs[ct].buffer = 0;
- mAttribs[ct].ptr = (const uint8_t*)alloc->getPtr();
- }
- }
-
- VertexArray va(mAttribs, mAttribCount);
- va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
-
- rsc->checkError("Mesh::renderPrimitiveRange 2");
- Primitive_t *prim = mPrimitives[primIndex];
- if (prim->mIndexBuffer.get()) {
- prim->mIndexBuffer->uploadCheck(rsc);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prim->mIndexBuffer->getBufferObjectID());
- glDrawElements(prim->mGLPrimitive, len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2));
- } else {
- glDrawArrays(prim->mGLPrimitive, start, len);
- }
-
- rsc->checkError("Mesh::renderPrimitiveRange");
+ mRSC->mHal.funcs.mesh.draw(mRSC, this, primIndex, start, len);
}
-
void Mesh::uploadAll(Context *rsc) {
- for (uint32_t ct = 0; ct < mVertexBufferCount; ct ++) {
- if (mVertexBuffers[ct].get()) {
- mVertexBuffers[ct]->deferedUploadToBufferObject(rsc);
- }
- }
-
- for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) {
- if (mPrimitives[ct]->mIndexBuffer.get()) {
- mPrimitives[ct]->mIndexBuffer->deferedUploadToBufferObject(rsc);
+ for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) {
+ if (mHal.state.vertexBuffers[ct].get()) {
+ rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.vertexBuffers[ct].get());
}
}
-}
-void Mesh::updateGLPrimitives() {
- for (uint32_t i = 0; i < mPrimitivesCount; i ++) {
- switch (mPrimitives[i]->mPrimitive) {
- case RS_PRIMITIVE_POINT: mPrimitives[i]->mGLPrimitive = GL_POINTS; break;
- case RS_PRIMITIVE_LINE: mPrimitives[i]->mGLPrimitive = GL_LINES; break;
- case RS_PRIMITIVE_LINE_STRIP: mPrimitives[i]->mGLPrimitive = GL_LINE_STRIP; break;
- case RS_PRIMITIVE_TRIANGLE: mPrimitives[i]->mGLPrimitive = GL_TRIANGLES; break;
- case RS_PRIMITIVE_TRIANGLE_STRIP: mPrimitives[i]->mGLPrimitive = GL_TRIANGLE_STRIP; break;
- case RS_PRIMITIVE_TRIANGLE_FAN: mPrimitives[i]->mGLPrimitive = GL_TRIANGLE_FAN; break;
+ for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
+ if (mHal.state.primitives[ct]->mIndexBuffer.get()) {
+ rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.primitives[ct]->mIndexBuffer.get());
}
}
}
@@ -312,8 +212,8 @@ void Mesh::computeBBox() {
uint32_t stride = 0;
uint32_t numVerts = 0;
// First we need to find the position ptr and stride
- for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
- const Type *bufferType = mVertexBuffers[ct]->getType();
+ for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) {
+ const Type *bufferType = mHal.state.vertexBuffers[ct]->getType();
const Element *bufferElem = bufferType->getElement();
for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) {
@@ -321,7 +221,7 @@ void Mesh::computeBBox() {
vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize();
stride = bufferElem->getSizeBytes() / sizeof(float);
uint32_t offset = bufferElem->getFieldOffsetBytes(ct);
- posPtr = (float*)((uint8_t*)mVertexBuffers[ct]->getPtr() + offset);
+ posPtr = (float*)((uint8_t*)mHal.state.vertexBuffers[ct]->getPtr() + offset);
numVerts = bufferType->getDimX();
break;
}
@@ -352,76 +252,58 @@ void Mesh::computeBBox() {
namespace android {
namespace renderscript {
-RsMesh rsi_MeshCreate(Context *rsc, uint32_t vtxCount, uint32_t idxCount) {
- Mesh *sm = new Mesh(rsc);
+RsMesh rsi_MeshCreate(Context *rsc,
+ RsAllocation * vtx, size_t vtxCount,
+ RsAllocation * idx, size_t idxCount,
+ uint32_t * primType, size_t primTypeCount) {
+ rsAssert(idxCount == primTypeCount);
+ Mesh *sm = new Mesh(rsc, vtxCount, idxCount);
sm->incUserRef();
- sm->mPrimitivesCount = idxCount;
- sm->mPrimitives = new Mesh::Primitive_t *[sm->mPrimitivesCount];
- for (uint32_t ct = 0; ct < idxCount; ct ++) {
- sm->mPrimitives[ct] = new Mesh::Primitive_t;
+ for (uint32_t i = 0; i < vtxCount; i ++) {
+ sm->setVertexBuffer((Allocation*)vtx[i], i);
}
- sm->mVertexBufferCount = vtxCount;
- sm->mVertexBuffers = new ObjectBaseRef<Allocation>[vtxCount];
-
- return sm;
-}
-
-void rsi_MeshBindVertex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t slot) {
- Mesh *sm = static_cast<Mesh *>(mv);
- rsAssert(slot < sm->mVertexBufferCount);
-
- sm->mVertexBuffers[slot].set((Allocation *)va);
-}
-
-void rsi_MeshBindIndex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t primType, uint32_t slot) {
- Mesh *sm = static_cast<Mesh *>(mv);
- rsAssert(slot < sm->mPrimitivesCount);
+ for (uint32_t i = 0; i < idxCount; i ++) {
+ sm->setPrimitive((Allocation*)idx[i], (RsPrimitive)primType[i], i);
+ }
- sm->mPrimitives[slot]->mIndexBuffer.set((Allocation *)va);
- sm->mPrimitives[slot]->mPrimitive = (RsPrimitive)primType;
- sm->updateGLPrimitives();
-}
+ sm->init();
-void rsi_MeshInitVertexAttribs(Context *rsc, RsMesh mv) {
- Mesh *sm = static_cast<Mesh *>(mv);
- sm->initVertexAttribs();
+ return sm;
}
}}
void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) {
Mesh *sm = static_cast<Mesh *>(mv);
- *numVtx = sm->mVertexBufferCount;
+ *numVtx = sm->mHal.state.vertexBuffersCount;
}
void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) {
Mesh *sm = static_cast<Mesh *>(mv);
- *numIdx = sm->mPrimitivesCount;
+ *numIdx = sm->mHal.state.primitivesCount;
}
void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) {
Mesh *sm = static_cast<Mesh *>(mv);
- rsAssert(vtxDataCount == sm->mVertexBufferCount);
+ rsAssert(vtxDataCount == sm->mHal.state.vertexBuffersCount);
for (uint32_t ct = 0; ct < vtxDataCount; ct ++) {
- vtxData[ct] = sm->mVertexBuffers[ct].get();
- sm->mVertexBuffers[ct]->incUserRef();
+ vtxData[ct] = sm->mHal.state.vertexBuffers[ct].get();
+ sm->mHal.state.vertexBuffers[ct]->incUserRef();
}
}
void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount) {
Mesh *sm = static_cast<Mesh *>(mv);
- rsAssert(idxDataCount == sm->mPrimitivesCount);
+ rsAssert(idxDataCount == sm->mHal.state.primitivesCount);
for (uint32_t ct = 0; ct < idxDataCount; ct ++) {
- va[ct] = sm->mPrimitives[ct]->mIndexBuffer.get();
- primType[ct] = sm->mPrimitives[ct]->mPrimitive;
- if (sm->mPrimitives[ct]->mIndexBuffer.get()) {
- sm->mPrimitives[ct]->mIndexBuffer->incUserRef();
+ va[ct] = sm->mHal.state.primitives[ct]->mIndexBuffer.get();
+ primType[ct] = sm->mHal.state.primitives[ct]->mPrimitive;
+ if (sm->mHal.state.primitives[ct]->mIndexBuffer.get()) {
+ sm->mHal.state.primitives[ct]->mIndexBuffer->incUserRef();
}
}
}
-
-#endif
diff --git a/libs/rs/rsMesh.h b/libs/rs/rsMesh.h
index 3e080e2..ed1e93d 100644
--- a/libs/rs/rsMesh.h
+++ b/libs/rs/rsMesh.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -29,57 +29,58 @@ namespace renderscript {
class Mesh : public ObjectBase {
public:
Mesh(Context *);
+ Mesh(Context *, uint32_t vertexBuffersCount, uint32_t primitivesCount);
~Mesh();
- // Contains vertex data
- // Position, normal, texcoord, etc could either be strided in one allocation
- // of provided separetely in multiple ones
- ObjectBaseRef<Allocation> *mVertexBuffers;
- uint32_t mVertexBufferCount;
-
// Either mIndexBuffer, mPrimitiveBuffer or both could have a NULL reference
// If both are null, mPrimitive only would be used to render the mesh
- struct Primitive_t
- {
+ struct Primitive_t {
ObjectBaseRef<Allocation> mIndexBuffer;
-
RsPrimitive mPrimitive;
- uint32_t mGLPrimitive;
};
- Primitive_t ** mPrimitives;
- uint32_t mPrimitivesCount;
-
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_MESH; }
static Mesh *createFromStream(Context *rsc, IStream *stream);
+ void init();
+
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ // Contains vertex data
+ // Position, normal, texcoord, etc could either be strided in one allocation
+ // of provided separetely in multiple ones
+ ObjectBaseRef<Allocation> *vertexBuffers;
+ uint32_t vertexBuffersCount;
+
+ Primitive_t ** primitives;
+ uint32_t primitivesCount;
+ };
+ State state;
+ };
+ Hal mHal;
+
+ void setVertexBuffer(Allocation *vb, uint32_t index) {
+ mHal.state.vertexBuffers[index].set(vb);
+ }
+
+ void setPrimitive(Allocation *idx, RsPrimitive prim, uint32_t index) {
+ mHal.state.primitives[index]->mIndexBuffer.set(idx);
+ mHal.state.primitives[index]->mPrimitive = prim;
+ }
-#ifndef ANDROID_RS_SERIALIZE
void render(Context *) const;
void renderPrimitive(Context *, uint32_t primIndex) const;
void renderPrimitiveRange(Context *, uint32_t primIndex, uint32_t start, uint32_t len) const;
void uploadAll(Context *);
- void updateGLPrimitives();
-
-
// Bounding volumes
float mBBoxMin[3];
float mBBoxMax[3];
void computeBBox();
-
- void initVertexAttribs();
-
protected:
- bool isValidGLComponent(const Element *elem, uint32_t fieldIdx);
- // Attribues that allow us to map to GL
- VertexArray::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
+ bool mInitialized;
};
class MeshContext {
@@ -92,7 +93,7 @@ public:
}
}
-#endif //ANDROID_RS_TRIANGLE_MESH_H
+#endif //ANDROID_RS_MESH_H
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
index 4ef05bf..b1d8f48 100644
--- a/libs/rs/rsProgram.cpp
+++ b/libs/rs/rsProgram.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -15,64 +15,47 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsProgram.h"
using namespace android;
using namespace android::renderscript;
-Program::Program(Context *rsc) : ObjectBase(rsc) {
- initMemberVars();
-}
-
Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
const uint32_t * params, uint32_t paramLength)
- : ObjectBase(rsc) {
+ : ProgramBase(rsc) {
initMemberVars();
for (uint32_t ct=0; ct < paramLength; ct+=2) {
if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
- mInputCount++;
- }
- if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
- mOutputCount++;
+ mHal.state.inputElementsCount++;
}
if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
- mConstantCount++;
+ mHal.state.constantsCount++;
}
if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
- mTextureCount++;
+ mHal.state.texturesCount++;
}
}
- mTextures = new ObjectBaseRef<Allocation>[mTextureCount];
- mSamplers = new ObjectBaseRef<Sampler>[mTextureCount];
- mTextureTargets = new RsTextureTarget[mTextureCount];
- mInputElements = new ObjectBaseRef<Element>[mInputCount];
- mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
- mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
- mConstants = new ObjectBaseRef<Allocation>[mConstantCount];
+ mHal.state.textures = new ObjectBaseRef<Allocation>[mHal.state.texturesCount];
+ mHal.state.samplers = new ObjectBaseRef<Sampler>[mHal.state.texturesCount];
+ mHal.state.textureTargets = new RsTextureTarget[mHal.state.texturesCount];
+ mHal.state.inputElements = new ObjectBaseRef<Element>[mHal.state.inputElementsCount];
+ mHal.state.constantTypes = new ObjectBaseRef<Type>[mHal.state.constantsCount];
+ mHal.state.constants = new ObjectBaseRef<Allocation>[mHal.state.constantsCount];
uint32_t input = 0;
- uint32_t output = 0;
uint32_t constant = 0;
uint32_t texture = 0;
for (uint32_t ct=0; ct < paramLength; ct+=2) {
if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
- mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
- }
- if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
- mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
+ mHal.state.inputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
}
if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
- mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
+ mHal.state.constantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
}
if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
- mTextureTargets[texture++] = (RsTextureTarget)params[ct+1];
+ mHal.state.textureTargets[texture++] = (RsTextureTarget)params[ct+1];
}
}
mIsInternal = false;
@@ -84,88 +67,69 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
shaderLength -= internalTokenLen;
}
mUserShader.setTo(shaderText, shaderLength);
-
- initAttribAndUniformArray();
}
Program::~Program() {
- if (mRSC->props.mLogShaders) {
- LOGV("Program::~Program with shader id %u", mShaderID);
- }
- if (mShaderID) {
- glDeleteShader(mShaderID);
- }
-
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
+ for (uint32_t ct=0; ct < mHal.state.constantsCount; ct++) {
bindAllocation(NULL, NULL, ct);
}
- for (uint32_t ct=0; ct < mTextureCount; ct++) {
+ for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) {
bindTexture(NULL, ct, NULL);
bindSampler(NULL, ct, NULL);
}
- delete[] mTextures;
- delete[] mSamplers;
- delete[] mTextureTargets;
- delete[] mInputElements;
- delete[] mOutputElements;
- delete[] mConstantTypes;
- delete[] mConstants;
- delete[] mAttribNames;
- delete[] mUniformNames;
- delete[] mUniformArraySizes;
- mInputCount = 0;
- mOutputCount = 0;
- mConstantCount = 0;
+ delete[] mHal.state.textures;
+ delete[] mHal.state.samplers;
+ delete[] mHal.state.textureTargets;
+ delete[] mHal.state.inputElements;
+ delete[] mHal.state.constantTypes;
+ delete[] mHal.state.constants;
+ mHal.state.inputElementsCount = 0;
+ mHal.state.constantsCount = 0;
+ mHal.state.texturesCount = 0;
}
void Program::initMemberVars() {
mDirty = true;
- mShaderID = 0;
- mAttribCount = 0;
- mUniformCount = 0;
- mTextureCount = 0;
- mTextures = NULL;
- mSamplers = NULL;
- mTextureTargets = NULL;
- mInputElements = NULL;
- mOutputElements = NULL;
- mConstantTypes = NULL;
- mConstants = NULL;
- mAttribNames = NULL;
- mUniformNames = NULL;
- mUniformArraySizes = NULL;
- mInputCount = 0;
- mOutputCount = 0;
- mConstantCount = 0;
- mIsValid = false;
+ mHal.drv = NULL;
+ mHal.state.textures = NULL;
+ mHal.state.samplers = NULL;
+ mHal.state.textureTargets = NULL;
+ mHal.state.inputElements = NULL;
+ mHal.state.constantTypes = NULL;
+ mHal.state.constants = NULL;
+
+ mHal.state.inputElementsCount = 0;
+ mHal.state.constantsCount = 0;
+ mHal.state.texturesCount = 0;
+
mIsInternal = false;
}
void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) {
if (alloc != NULL) {
- if (slot >= mConstantCount) {
+ if (slot >= mHal.state.constantsCount) {
LOGE("Attempt to bind alloc at slot %u, on shader id %u, but const count is %u",
- slot, (uint32_t)this, mConstantCount);
+ slot, (uint32_t)this, mHal.state.constantsCount);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
return;
}
- if (!alloc->getType()->isEqual(mConstantTypes[slot].get())) {
+ if (!alloc->getType()->isEqual(mHal.state.constantTypes[slot].get())) {
LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch",
slot, (uint32_t)this);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
return;
}
}
- if (mConstants[slot].get() == alloc) {
+ if (mHal.state.constants[slot].get() == alloc) {
return;
}
- if (mConstants[slot].get()) {
- mConstants[slot].get()->removeProgramToDirty(this);
+ if (mHal.state.constants[slot].get()) {
+ mHal.state.constants[slot].get()->removeProgramToDirty(this);
}
- mConstants[slot].set(alloc);
+ mHal.state.constants[slot].set(alloc);
if (alloc) {
alloc->addProgramToDirty(this);
}
@@ -173,327 +137,33 @@ void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) {
}
void Program::bindTexture(Context *rsc, uint32_t slot, Allocation *a) {
- if (slot >= mTextureCount) {
- LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mTextureCount);
+ if (slot >= mHal.state.texturesCount) {
+ LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mHal.state.texturesCount);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind texture");
return;
}
- if (a && a->getType()->getDimFaces() && mTextureTargets[slot] != RS_TEXTURE_CUBE) {
+ if (a && a->getType()->getDimFaces() && mHal.state.textureTargets[slot] != RS_TEXTURE_CUBE) {
LOGE("Attempt to bind cubemap to slot %u but 2d texture needed", slot);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind cubemap to 2d texture slot");
return;
}
- //LOGE("bindtex %i %p", slot, a);
- mTextures[slot].set(a);
+ mHal.state.textures[slot].set(a);
mDirty = true;
}
void Program::bindSampler(Context *rsc, uint32_t slot, Sampler *s) {
- if (slot >= mTextureCount) {
- LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mTextureCount);
+ if (slot >= mHal.state.texturesCount) {
+ LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mHal.state.texturesCount);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind sampler");
return;
}
- mSamplers[slot].set(s);
+ mHal.state.samplers[slot].set(s);
mDirty = true;
}
-String8 Program::getGLSLInputString() const {
- String8 s;
- for (uint32_t ct=0; ct < mInputCount; ct++) {
- const Element *e = mInputElements[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;
-}
-
-String8 Program::getGLSLOutputString() const {
- return String8();
-}
-
-String8 Program::getGLSLConstantString() const {
- return String8();
-}
-
-void Program::createShader() {
-}
-
-bool Program::loadShader(Context *rsc, uint32_t type) {
- mShaderID = glCreateShader(type);
- rsAssert(mShaderID);
-
- if (rsc->props.mLogShaders) {
- LOGV("Loading shader type %x, ID %i", type, 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 Program::setShader(const char *txt, uint32_t len) {
- mUserShader.setTo(txt, len);
-}
-
-void Program::appendUserConstants() {
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- const Element *e = mConstantTypes[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 Program::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 Program::setUniform(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 Program::setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment) {
- uint32_t uidx = 0;
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- Allocation *alloc = mConstants[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 = mConstantTypes[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 Program::initAttribAndUniformArray() {
- mAttribCount = 0;
- for (uint32_t ct=0; ct < mInputCount; ct++) {
- const Element *elem = mInputElements[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 < mConstantCount; ct++) {
- const Element *elem = mConstantTypes[ct]->getElement();
-
- for (uint32_t field=0; field < elem->getFieldCount(); field++) {
- if (elem->getFieldName(field)[0] != '#') {
- mUniformCount ++;
- }
- }
- }
- mUniformCount += mTextureCount;
-
- if (mAttribCount) {
- mAttribNames = new String8[mAttribCount];
- }
- if (mUniformCount) {
- mUniformNames = new String8[mUniformCount];
- mUniformArraySizes = new uint32_t[mUniformCount];
- }
-}
-
-void Program::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)++;
- }
- }
-}
-
namespace android {
namespace renderscript {
diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h
index c48464d..948ba3e 100644
--- a/libs/rs/rsProgram.h
+++ b/libs/rs/rsProgram.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -17,101 +17,68 @@
#ifndef ANDROID_RS_PROGRAM_H
#define ANDROID_RS_PROGRAM_H
-#include "rsObjectBase.h"
+#include "rsProgramBase.h"
#include "rsElement.h"
// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
-class ShaderCache;
#define RS_SHADER_INTERNAL "//rs_shader_internal\n"
#define RS_SHADER_ATTR "ATTRIB_"
#define RS_SHADER_UNI "UNI_"
-class Program : public ObjectBase {
+class Program : public ProgramBase {
public:
- Program(Context *);
Program(Context *, const char * shaderText, uint32_t shaderLength,
const uint32_t * params, uint32_t paramLength);
virtual ~Program();
void bindAllocation(Context *, Allocation *, uint32_t slot);
- virtual void createShader();
bool isUserProgram() const {return !mIsInternal;}
void bindTexture(Context *, uint32_t slot, Allocation *);
void bindSampler(Context *, uint32_t slot, Sampler *);
- uint32_t getShaderID() const {return mShaderID;}
- void setShader(const char *, uint32_t len);
-
- uint32_t getAttribCount() const {return mAttribCount;}
- uint32_t getUniformCount() const {return mUniformCount;}
- const String8 & getAttribName(uint32_t i) const {return mAttribNames[i];}
- const String8 & getUniformName(uint32_t i) const {return mUniformNames[i];}
- uint32_t getUniformArraySize(uint32_t i) const {return mUniformArraySizes[i];}
-
- String8 getGLSLInputString() const;
- String8 getGLSLOutputString() const;
- String8 getGLSLConstantString() const;
-
- bool isValid() const {return mIsValid;}
- void forceDirty() const {mDirty = true;}
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ // The difference between Textures and Constants is how they are accessed
+ // Texture lookups go though a sampler which in effect converts normalized
+ // coordinates into type specific. Multiple samples may also be taken
+ // and filtered.
+ //
+ // Constants are strictly accessed by the shader code
+ ObjectBaseRef<Allocation> *textures;
+ RsTextureTarget *textureTargets;
+ uint32_t texturesCount;
+
+ ObjectBaseRef<Sampler> *samplers;
+ uint32_t samplersCount;
+
+ ObjectBaseRef<Allocation> *constants;
+ ObjectBaseRef<Type> *constantTypes;
+ uint32_t constantsCount;
+
+ ObjectBaseRef<Element> *inputElements;
+ uint32_t inputElementsCount;
+ };
+ State state;
+ };
+ Hal mHal;
protected:
- // Components not listed in "in" will be passed though
- // unless overwritten by components in out.
- ObjectBaseRef<Element> *mInputElements;
- ObjectBaseRef<Element> *mOutputElements;
- ObjectBaseRef<Type> *mConstantTypes;
- ObjectBaseRef<Allocation> *mConstants;
- uint32_t mInputCount;
- uint32_t mOutputCount;
- uint32_t mConstantCount;
- bool mIsValid;
bool mIsInternal;
-
- // Applies to vertex and fragment shaders only
- void appendUserConstants();
- void setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment);
- void initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix);
-
- void initAttribAndUniformArray();
-
- mutable bool mDirty;
- String8 mShader;
String8 mUserShader;
- uint32_t mShaderID;
-
- uint32_t mTextureCount;
- uint32_t mAttribCount;
- uint32_t mUniformCount;
- String8 *mAttribNames;
- String8 *mUniformNames;
- uint32_t *mUniformArraySizes;
-
- void logUniform(const Element *field, const float *fd, uint32_t arraySize );
- void setUniform(Context *rsc, const Element *field, const float *fd, int32_t slot, uint32_t arraySize );
void initMemberVars();
-
- // The difference between Textures and Constants is how they are accessed
- // Texture lookups go though a sampler which in effect converts normalized
- // coordinates into type specific. Multiple samples may also be taken
- // and filtered.
- //
- // Constants are strictly accessed by programetic loads.
- ObjectBaseRef<Allocation> *mTextures;
- ObjectBaseRef<Sampler> *mSamplers;
- RsTextureTarget *mTextureTargets;
- bool loadShader(Context *, uint32_t type);
};
}
}
-#endif
+#endif // ANDROID_RS_PROGRAM_H
diff --git a/libs/rs/rsProgramBase.h b/libs/rs/rsProgramBase.h
new file mode 100644
index 0000000..80da453
--- /dev/null
+++ b/libs/rs/rsProgramBase.h
@@ -0,0 +1,44 @@
+/*
+ * 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_RS_PROGRAM_BASE_H
+#define ANDROID_RS_PROGRAM_BASE_H
+
+#include "rsObjectBase.h"
+#include "rsElement.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class ProgramBase : public ObjectBase {
+public:
+ ProgramBase(Context *rsc) : ObjectBase(rsc) {
+ mDirty = true;
+ }
+
+ void forceDirty() const {mDirty = true;}
+
+protected:
+ mutable bool mDirty;
+};
+
+}
+}
+#endif // ANDROID_RS_PROGRAM_BASE_H
+
+
+
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index ff314b7..356ff77 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -15,13 +15,6 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsProgramFragment.h"
using namespace android;
@@ -31,19 +24,16 @@ ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText,
uint32_t shaderLength, const uint32_t * params,
uint32_t paramLength)
: Program(rsc, shaderText, shaderLength, params, paramLength) {
-
mConstantColor[0] = 1.f;
mConstantColor[1] = 1.f;
mConstantColor[2] = 1.f;
mConstantColor[3] = 1.f;
- init(rsc);
+ mRSC->mHal.funcs.fragment.init(mRSC, this, mUserShader.string(), mUserShader.length());
}
ProgramFragment::~ProgramFragment() {
- if (mShaderID) {
- mRSC->mShaderCache.cleanupFragment(mShaderID);
- }
+ mRSC->mHal.funcs.fragment.destroy(mRSC, this);
}
void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b, float a) {
@@ -52,7 +42,7 @@ void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b,
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set fixed function emulation color on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
LOGE("Unable to set fixed function emulation color because allocation is missing");
rsc->setError(RS_ERROR_BAD_SHADER, "Unable to set fixed function emulation color because allocation is missing");
return;
@@ -61,107 +51,25 @@ void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b,
mConstantColor[1] = g;
mConstantColor[2] = b;
mConstantColor[3] = a;
- memcpy(mConstants[0]->getPtr(), mConstantColor, 4*sizeof(float));
+ memcpy(mHal.state.constants[0]->getPtr(), mConstantColor, 4*sizeof(float));
mDirty = true;
}
-void ProgramFragment::setupGL2(Context *rsc, ProgramFragmentState *state, ShaderCache *sc) {
- //LOGE("sgl2 frag1 %x", glGetError());
+void ProgramFragment::setup(Context *rsc, ProgramFragmentState *state) {
if ((state->mLast.get() == this) && !mDirty) {
return;
}
state->mLast.set(this);
- rsc->checkError("ProgramFragment::setupGL2 start");
-
- rsc->checkError("ProgramFragment::setupGL2 begin uniforms");
- setupUserConstants(rsc, sc, true);
-
- uint32_t numTexturesToBind = mTextureCount;
- uint32_t numTexturesAvailable = rsc->getMaxFragmentTextures();
- if (numTexturesToBind >= numTexturesAvailable) {
- LOGE("Attempting to bind %u textures on shader id %u, but only %u are available",
- mTextureCount, (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 (!mTextures[ct].get()) {
+ for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) {
+ if (!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;
}
-
- mTextures[ct]->uploadCheck(rsc);
- GLenum target = (GLenum)mTextures[ct]->getGLTarget();
- if (target != GL_TEXTURE_2D && target != 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(target, mTextures[ct]->getTextureID());
- rsc->checkError("ProgramFragment::setupGL2 tex bind");
- if (mSamplers[ct].get()) {
- mSamplers[ct]->setupGL(rsc, mTextures[ct].get());
- } else {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- rsc->checkError("ProgramFragment::setupGL2 tex env");
- }
-
- glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
- rsc->checkError("ProgramFragment::setupGL2 uniforms");
- }
-
- glActiveTexture(GL_TEXTURE0);
- mDirty = false;
- rsc->checkError("ProgramFragment::setupGL2");
-}
-
-void ProgramFragment::loadShader(Context *rsc) {
- Program::loadShader(rsc, GL_FRAGMENT_SHADER);
-}
-
-void ProgramFragment::createShader() {
- if (mUserShader.length() > 1) {
- mShader.append("precision mediump float;\n");
- appendUserConstants();
- char buf[256];
- for (uint32_t ct=0; ct < mTextureCount; ct++) {
- if (mTextureTargets[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);
- }
- mShader.append(mUserShader);
- } else {
- LOGE("ProgramFragment::createShader cannot create program, shader code not defined");
- rsAssert(0);
- }
-}
-
-void ProgramFragment::init(Context *rsc) {
- uint32_t uniformIndex = 0;
- if (mUserShader.size() > 0) {
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformIndex, RS_SHADER_UNI);
- }
- }
- mTextureUniformIndexStart = uniformIndex;
- char buf[256];
- for (uint32_t ct=0; ct < mTextureCount; ct++) {
- snprintf(buf, sizeof(buf), "UNI_Tex%i", ct);
- mUniformNames[uniformIndex].setTo(buf);
- mUniformArraySizes[uniformIndex] = 1;
- uniformIndex++;
}
- createShader();
+ rsc->mHal.funcs.fragment.setActive(rsc, this);
}
void ProgramFragment::serialize(OStream *stream) const {
@@ -200,7 +108,8 @@ void ProgramFragmentState::init(Context *rsc) {
tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
tmp[1] = (uint32_t)inputType;
- Allocation *constAlloc = new Allocation(rsc, inputType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
+ Allocation *constAlloc = Allocation::createAllocation(rsc, inputType,
+ RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(),
shaderString.length(), tmp, 2);
pf->bindAllocation(rsc, constAlloc, 0);
@@ -218,8 +127,8 @@ namespace android {
namespace renderscript {
RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc, const char * shaderText,
- uint32_t shaderLength, const uint32_t * params,
- uint32_t paramLength) {
+ size_t shaderLength, const uint32_t * params,
+ size_t paramLength) {
ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength);
pf->incUserRef();
//LOGE("rsi_ProgramFragmentCreate %p", pf);
diff --git a/libs/rs/rsProgramFragment.h b/libs/rs/rsProgramFragment.h
index 3d28946..d6e20cd 100644
--- a/libs/rs/rsProgramFragment.h
+++ b/libs/rs/rsProgramFragment.h
@@ -32,11 +32,8 @@ public:
uint32_t paramLength);
virtual ~ProgramFragment();
- virtual void setupGL2(Context *, ProgramFragmentState *, ShaderCache *sc);
+ virtual void setup(Context *, ProgramFragmentState *);
- virtual void createShader();
- virtual void loadShader(Context *rsc);
- virtual void init(Context *rsc);
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_FRAGMENT; }
static ProgramFragment *createFromStream(Context *rsc, IStream *stream);
diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp
index ace1572..435561d 100644
--- a/libs/rs/rsProgramRaster.cpp
+++ b/libs/rs/rsProgramRaster.cpp
@@ -15,11 +15,6 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsProgramRaster.h"
using namespace android;
@@ -27,49 +22,33 @@ using namespace android::renderscript;
ProgramRaster::ProgramRaster(Context *rsc, bool pointSmooth,
- bool lineSmooth, bool pointSprite)
- : Program(rsc) {
-
- mPointSmooth = pointSmooth;
- mLineSmooth = lineSmooth;
- mPointSprite = pointSprite;
- mLineWidth = 1.0f;
- mCull = RS_CULL_BACK;
-}
+ bool lineSmooth, bool pointSprite,
+ float lineWidth, RsCullMode cull)
+ : ProgramBase(rsc) {
-ProgramRaster::~ProgramRaster() {
-}
+ memset(&mHal, 0, sizeof(mHal));
+
+ mHal.state.pointSmooth = pointSmooth;
+ mHal.state.lineSmooth = lineSmooth;
+ mHal.state.pointSprite = pointSprite;
+ mHal.state.lineWidth = lineWidth;
+ mHal.state.cull = cull;
-void ProgramRaster::setLineWidth(float s) {
- mLineWidth = s;
- mDirty = true;
+ rsc->mHal.funcs.raster.init(rsc, this);
}
-void ProgramRaster::setCullMode(RsCullMode mode) {
- mCull = mode;
- mDirty = true;
+ProgramRaster::~ProgramRaster() {
+ mRSC->mHal.funcs.raster.destroy(mRSC, this);
}
-void ProgramRaster::setupGL2(const Context *rsc, ProgramRasterState *state) {
+void ProgramRaster::setup(const Context *rsc, ProgramRasterState *state) {
if (state->mLast.get() == this && !mDirty) {
return;
}
state->mLast.set(this);
mDirty = false;
- switch (mCull) {
- 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;
- }
+ rsc->mHal.funcs.raster.setActive(rsc, this);
}
void ProgramRaster::serialize(OStream *stream) const {
@@ -86,7 +65,7 @@ ProgramRasterState::~ProgramRasterState() {
}
void ProgramRasterState::init(Context *rsc) {
- ProgramRaster *pr = new ProgramRaster(rsc, false, false, false);
+ ProgramRaster *pr = new ProgramRaster(rsc, false, false, false, 1.f, RS_CULL_BACK);
mDefault.set(pr);
}
@@ -101,27 +80,15 @@ namespace renderscript {
RsProgramRaster rsi_ProgramRasterCreate(Context * rsc,
bool pointSmooth,
bool lineSmooth,
- bool pointSprite) {
+ bool pointSprite,
+ float lineWidth,
+ RsCullMode cull) {
ProgramRaster *pr = new ProgramRaster(rsc, pointSmooth,
- lineSmooth, pointSprite);
+ lineSmooth, pointSprite, lineWidth, cull);
pr->incUserRef();
return pr;
}
-void rsi_ProgramRasterSetLineWidth(Context * rsc,
- RsProgramRaster vpr,
- float s) {
- ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
- pr->setLineWidth(s);
-}
-
-void rsi_ProgramRasterSetCullMode(Context * rsc,
- RsProgramRaster vpr,
- RsCullMode mode) {
- ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
- pr->setCullMode(mode);
-}
-
}
}
diff --git a/libs/rs/rsProgramRaster.h b/libs/rs/rsProgramRaster.h
index 7958af9..efdb948 100644
--- a/libs/rs/rsProgramRaster.h
+++ b/libs/rs/rsProgramRaster.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-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.
@@ -17,7 +17,7 @@
#ifndef ANDROID_RS_PROGRAM_RASTER_H
#define ANDROID_RS_PROGRAM_RASTER_H
-#include "rsProgram.h"
+#include "rsProgramBase.h"
// ---------------------------------------------------------------------------
namespace android {
@@ -25,28 +25,36 @@ namespace renderscript {
class ProgramRasterState;
-class ProgramRaster : public Program {
+class ProgramRaster : public ProgramBase {
public:
ProgramRaster(Context *rsc,
bool pointSmooth,
bool lineSmooth,
- bool pointSprite);
+ bool pointSprite,
+ float lineWidth,
+ RsCullMode cull);
virtual ~ProgramRaster();
- virtual void setupGL2(const Context *, ProgramRasterState *);
+ virtual void setup(const Context *, ProgramRasterState *);
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_RASTER; }
static ProgramRaster *createFromStream(Context *rsc, IStream *stream);
- void setLineWidth(float w);
- void setCullMode(RsCullMode mode);
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ bool pointSmooth;
+ bool lineSmooth;
+ bool pointSprite;
+ float lineWidth;
+ RsCullMode cull;
+ };
+ State state;
+ };
+ Hal mHal;
protected:
- bool mPointSmooth;
- bool mLineSmooth;
- bool mPointSprite;
- float mLineWidth;
- RsCullMode mCull;
};
class ProgramRasterState {
diff --git a/libs/rs/rsProgramStore.cpp b/libs/rs/rsProgramStore.cpp
index 09b759d..8fe890b 100644
--- a/libs/rs/rsProgramStore.cpp
+++ b/libs/rs/rsProgramStore.cpp
@@ -15,82 +15,43 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsProgramStore.h"
using namespace android;
using namespace android::renderscript;
-ProgramStore::ProgramStore(Context *rsc) : Program(rsc) {
- mDitherEnable = true;
- mBlendEnable = false;
- mColorRWriteEnable = true;
- mColorGWriteEnable = true;
- mColorBWriteEnable = true;
- mColorAWriteEnable = true;
- mBlendSrc = GL_ONE;
- mBlendDst = GL_ZERO;
+ProgramStore::ProgramStore(Context *rsc,
+ bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA,
+ bool depthMask, bool ditherEnable,
+ RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
+ RsDepthFunc depthFunc) : ProgramBase(rsc) {
+ memset(&mHal, 0, sizeof(mHal));
+
+ mHal.state.ditherEnable = ditherEnable;
+
+ mHal.state.colorRWriteEnable = colorMaskR;
+ mHal.state.colorGWriteEnable = colorMaskG;
+ mHal.state.colorBWriteEnable = colorMaskB;
+ mHal.state.colorAWriteEnable = colorMaskA;
+ mHal.state.blendSrc = srcFunc;
+ mHal.state.blendDst = destFunc;
- mDepthTestEnable = false;
- mDepthWriteEnable = true;
- mDepthFunc = GL_LESS;
+ mHal.state.depthWriteEnable = depthMask;
+ mHal.state.depthFunc = depthFunc;
}
ProgramStore::~ProgramStore() {
+ mRSC->mHal.funcs.store.destroy(mRSC, this);
}
-void ProgramStore::setupGL2(const Context *rsc, ProgramStoreState *state) {
+void ProgramStore::setup(const Context *rsc, ProgramStoreState *state) {
if (state->mLast.get() == this) {
return;
}
state->mLast.set(this);
- glColorMask(mColorRWriteEnable,
- mColorGWriteEnable,
- mColorBWriteEnable,
- mColorAWriteEnable);
- if (mBlendEnable) {
- glEnable(GL_BLEND);
- glBlendFunc(mBlendSrc, mBlendDst);
- } else {
- glDisable(GL_BLEND);
- }
-
- //LOGE("pfs %i, %i, %x", mDepthWriteEnable, mDepthTestEnable, mDepthFunc);
-
- if (rsc->mUserSurfaceConfig.depthMin > 0) {
- glDepthMask(mDepthWriteEnable);
- if (mDepthTestEnable || mDepthWriteEnable) {
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(mDepthFunc);
- } 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 (mDitherEnable) {
- glEnable(GL_DITHER);
- } else {
- glDisable(GL_DITHER);
- }
-}
-
-void ProgramStore::setDitherEnable(bool enable) {
- mDitherEnable = enable;
+ rsc->mHal.funcs.store.setActive(rsc, this);
}
void ProgramStore::serialize(OStream *stream) const {
@@ -100,123 +61,24 @@ ProgramStore *ProgramStore::createFromStream(Context *rsc, IStream *stream) {
return NULL;
}
-void ProgramStore::setDepthFunc(RsDepthFunc func) {
- mDepthTestEnable = true;
-
- switch (func) {
- case RS_DEPTH_FUNC_ALWAYS:
- mDepthTestEnable = false;
- mDepthFunc = GL_ALWAYS;
- break;
- case RS_DEPTH_FUNC_LESS:
- mDepthFunc = GL_LESS;
- break;
- case RS_DEPTH_FUNC_LEQUAL:
- mDepthFunc = GL_LEQUAL;
- break;
- case RS_DEPTH_FUNC_GREATER:
- mDepthFunc = GL_GREATER;
- break;
- case RS_DEPTH_FUNC_GEQUAL:
- mDepthFunc = GL_GEQUAL;
- break;
- case RS_DEPTH_FUNC_EQUAL:
- mDepthFunc = GL_EQUAL;
- break;
- case RS_DEPTH_FUNC_NOTEQUAL:
- mDepthFunc = GL_NOTEQUAL;
- break;
- }
-}
-
-void ProgramStore::setDepthMask(bool mask) {
- mDepthWriteEnable = mask;
-}
-
-void ProgramStore::setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst) {
- mBlendEnable = true;
- if ((src == RS_BLEND_SRC_ONE) &&
- (dst == RS_BLEND_DST_ZERO)) {
- mBlendEnable = false;
- }
-
- switch (src) {
- case RS_BLEND_SRC_ZERO:
- mBlendSrc = GL_ZERO;
- break;
- case RS_BLEND_SRC_ONE:
- mBlendSrc = GL_ONE;
- break;
- case RS_BLEND_SRC_DST_COLOR:
- mBlendSrc = GL_DST_COLOR;
- break;
- case RS_BLEND_SRC_ONE_MINUS_DST_COLOR:
- mBlendSrc = GL_ONE_MINUS_DST_COLOR;
- break;
- case RS_BLEND_SRC_SRC_ALPHA:
- mBlendSrc = GL_SRC_ALPHA;
- break;
- case RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA:
- mBlendSrc = GL_ONE_MINUS_SRC_ALPHA;
- break;
- case RS_BLEND_SRC_DST_ALPHA:
- mBlendSrc = GL_DST_ALPHA;
- break;
- case RS_BLEND_SRC_ONE_MINUS_DST_ALPHA:
- mBlendSrc = GL_ONE_MINUS_DST_ALPHA;
- break;
- case RS_BLEND_SRC_SRC_ALPHA_SATURATE:
- mBlendSrc = GL_SRC_ALPHA_SATURATE;
- break;
- }
-
- switch (dst) {
- case RS_BLEND_DST_ZERO:
- mBlendDst = GL_ZERO;
- break;
- case RS_BLEND_DST_ONE:
- mBlendDst = GL_ONE;
- break;
- case RS_BLEND_DST_SRC_COLOR:
- mBlendDst = GL_SRC_COLOR;
- break;
- case RS_BLEND_DST_ONE_MINUS_SRC_COLOR:
- mBlendDst = GL_ONE_MINUS_SRC_COLOR;
- break;
- case RS_BLEND_DST_SRC_ALPHA:
- mBlendDst = GL_SRC_ALPHA;
- break;
- case RS_BLEND_DST_ONE_MINUS_SRC_ALPHA:
- mBlendDst = GL_ONE_MINUS_SRC_ALPHA;
- break;
- case RS_BLEND_DST_DST_ALPHA:
- mBlendDst = GL_DST_ALPHA;
- break;
- case RS_BLEND_DST_ONE_MINUS_DST_ALPHA:
- mBlendDst = GL_ONE_MINUS_DST_ALPHA;
- break;
- }
-}
-
-void ProgramStore::setColorMask(bool r, bool g, bool b, bool a) {
- mColorRWriteEnable = r;
- mColorGWriteEnable = g;
- mColorBWriteEnable = b;
- mColorAWriteEnable = a;
+void ProgramStore::init() {
+ mRSC->mHal.funcs.store.init(mRSC, this);
}
ProgramStoreState::ProgramStoreState() {
- mPFS = NULL;
}
ProgramStoreState::~ProgramStoreState() {
- ObjectBase::checkDelete(mPFS);
- mPFS = NULL;
}
void ProgramStoreState::init(Context *rsc) {
- ProgramStore *pfs = new ProgramStore(rsc);
- mDefault.set(pfs);
+ ProgramStore *ps = new ProgramStore(rsc,
+ true, true, true, true,
+ true, true,
+ RS_BLEND_SRC_ONE, RS_BLEND_DST_ZERO,
+ RS_DEPTH_FUNC_LESS);
+ ps->init();
+ mDefault.set(ps);
}
void ProgramStoreState::deinit(Context *rsc) {
@@ -224,40 +86,24 @@ void ProgramStoreState::deinit(Context *rsc) {
mLast.clear();
}
+
namespace android {
namespace renderscript {
-void rsi_ProgramStoreBegin(Context * rsc, RsElement in, RsElement out) {
- ObjectBase::checkDelete(rsc->mStateFragmentStore.mPFS);
- rsc->mStateFragmentStore.mPFS = new ProgramStore(rsc);
-}
-
-void rsi_ProgramStoreDepthFunc(Context *rsc, RsDepthFunc func) {
- rsc->mStateFragmentStore.mPFS->setDepthFunc(func);
-}
-
-void rsi_ProgramStoreDepthMask(Context *rsc, bool mask) {
- rsc->mStateFragmentStore.mPFS->setDepthMask(mask);
-}
-
-void rsi_ProgramStoreColorMask(Context *rsc, bool r, bool g, bool b, bool a) {
- rsc->mStateFragmentStore.mPFS->setColorMask(r, g, b, a);
-}
-
-void rsi_ProgramStoreBlendFunc(Context *rsc, RsBlendSrcFunc src, RsBlendDstFunc dst) {
- rsc->mStateFragmentStore.mPFS->setBlendFunc(src, dst);
-}
-
-RsProgramStore rsi_ProgramStoreCreate(Context *rsc) {
- ProgramStore *pfs = rsc->mStateFragmentStore.mPFS;
+RsProgramStore rsi_ProgramStoreCreate(Context *rsc,
+ bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA,
+ bool depthMask, bool ditherEnable,
+ RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
+ RsDepthFunc depthFunc) {
+
+ ProgramStore *pfs = new ProgramStore(rsc,
+ colorMaskR, colorMaskG, colorMaskB, colorMaskA,
+ depthMask, ditherEnable,
+ srcFunc, destFunc, depthFunc);
+ pfs->init();
pfs->incUserRef();
- rsc->mStateFragmentStore.mPFS = 0;
return pfs;
}
-void rsi_ProgramStoreDither(Context *rsc, bool enable) {
- rsc->mStateFragmentStore.mPFS->setDitherEnable(enable);
-}
-
}
}
diff --git a/libs/rs/rsProgramStore.h b/libs/rs/rsProgramStore.h
index f8eb7cf..77b3881 100644
--- a/libs/rs/rsProgramStore.h
+++ b/libs/rs/rsProgramStore.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -17,7 +17,7 @@
#ifndef ANDROID_RS_PROGRAM_FRAGMENT_STORE_H
#define ANDROID_RS_PROGRAM_FRAGMENT_STORE_H
-#include "rsProgram.h"
+#include "rsProgramBase.h"
#include "rsStream.h"
// ---------------------------------------------------------------------------
@@ -26,41 +26,46 @@ namespace renderscript {
class ProgramStoreState;
-class ProgramStore : public Program {
+class ProgramStore : public ProgramBase {
public:
- ProgramStore(Context *);
+ ProgramStore(Context *,
+ bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA,
+ bool depthMask, bool ditherEnable,
+ RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
+ RsDepthFunc depthFunc);
virtual ~ProgramStore();
- virtual void setupGL2(const Context *, ProgramStoreState *);
-
- void setDepthFunc(RsDepthFunc);
- void setDepthMask(bool);
-
- void setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst);
- void setColorMask(bool, bool, bool, bool);
-
- void setDitherEnable(bool);
+ virtual void setup(const Context *, ProgramStoreState *);
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_STORE; }
static ProgramStore *createFromStream(Context *rsc, IStream *stream);
-protected:
- bool mDitherEnable;
+ void init();
+
+ struct Hal {
+ mutable void *drv;
- bool mBlendEnable;
- bool mColorRWriteEnable;
- bool mColorGWriteEnable;
- bool mColorBWriteEnable;
- bool mColorAWriteEnable;
- int32_t mBlendSrc;
- int32_t mBlendDst;
+ struct State {
+ bool ditherEnable;
- bool mDepthTestEnable;
- bool mDepthWriteEnable;
- int32_t mDepthFunc;
+ //bool blendEnable;
+ bool colorRWriteEnable;
+ bool colorGWriteEnable;
+ bool colorBWriteEnable;
+ bool colorAWriteEnable;
+ RsBlendSrcFunc blendSrc;
+ RsBlendDstFunc blendDst;
- bool mStencilTestEnable;
+ //bool depthTestEnable;
+ bool depthWriteEnable;
+ RsDepthFunc depthFunc;
+ };
+ State state;
+ };
+ Hal mHal;
+
+protected:
};
class ProgramStoreState {
@@ -72,9 +77,6 @@ public:
ObjectBaseRef<ProgramStore> mDefault;
ObjectBaseRef<ProgramStore> mLast;
-
-
- ProgramStore *mPFS;
};
}
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 403c2a6..058a456 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -15,13 +15,6 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsProgramVertex.h"
using namespace android;
@@ -32,73 +25,28 @@ ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText,
uint32_t shaderLength, const uint32_t * params,
uint32_t paramLength)
: Program(rsc, shaderText, shaderLength, params, paramLength) {
- init(rsc);
+ mRSC->mHal.funcs.vertex.init(mRSC, this, mUserShader.string(), mUserShader.length());
}
ProgramVertex::~ProgramVertex() {
- if (mShaderID) {
- mRSC->mShaderCache.cleanupVertex(mShaderID);
- }
-}
-
-void ProgramVertex::loadShader(Context *rsc) {
- Program::loadShader(rsc, GL_VERTEX_SHADER);
-}
-
-void ProgramVertex::createShader(Context *rsc) {
- if (mUserShader.length() > 1) {
-
- appendUserConstants();
-
- for (uint32_t ct=0; ct < mInputCount; ct++) {
- const Element *e = mInputElements[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");
- }
- }
- mShader.append(mUserShader);
- } else {
- rsc->setError(RS_ERROR_FATAL_UNKNOWN,
- "ProgramFragment::createShader cannot create program, shader code not defined");
- }
+ mRSC->mHal.funcs.vertex.destroy(mRSC, this);
}
-void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc) {
+void ProgramVertex::setup(Context *rsc, ProgramVertexState *state) {
if ((state->mLast.get() == this) && !mDirty) {
return;
}
- rsc->checkError("ProgramVertex::setupGL2 start");
-
if (!isUserProgram()) {
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to set fixed function emulation matrices because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
- Matrix mvp;
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
+ Matrix4x4 mvp;
mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
- Matrix t;
+ Matrix4x4 t;
t.load(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
mvp.multiply(&t);
for (uint32_t i = 0; i < 16; i ++) {
@@ -106,11 +54,9 @@ void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCach
}
}
- rsc->checkError("ProgramVertex::setupGL2 begin uniforms");
- setupUserConstants(rsc, sc, false);
-
state->mLast.set(this);
- rsc->checkError("ProgramVertex::setupGL2");
+
+ rsc->mHal.funcs.vertex.setActive(rsc, this);
}
void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const {
@@ -119,12 +65,12 @@ void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const
"Attempting to set fixed function emulation matrix projection on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to set fixed function emulation matrix projection because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
mDirty = true;
}
@@ -135,12 +81,12 @@ void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const
"Attempting to set fixed function emulation matrix modelview on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to set fixed function emulation matrix modelview because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
mDirty = true;
}
@@ -151,12 +97,12 @@ void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const {
"Attempting to set fixed function emulation matrix texture on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to set fixed function emulation matrix texture because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
mDirty = true;
}
@@ -167,12 +113,12 @@ void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const {
"Attempting to get fixed function emulation matrix projection on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to get fixed function emulation matrix projection because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
memcpy(m, &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], sizeof(rsc_Matrix));
}
@@ -180,27 +126,13 @@ void ProgramVertex::transformToScreen(Context *rsc, float *v4out, const float *v
if (isUserProgram()) {
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
- Matrix mvp;
- mvp.loadMultiply((Matrix *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
- (Matrix *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
+ Matrix4x4 mvp;
+ mvp.loadMultiply((Matrix4x4 *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
+ (Matrix4x4 *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
mvp.vectorMultiply(v4out, v3in);
}
-void ProgramVertex::init(Context *rsc) {
- uint32_t attribCount = 0;
- uint32_t uniformCount = 0;
- if (mUserShader.size() > 0) {
- for (uint32_t ct=0; ct < mInputCount; ct++) {
- initAddUserElement(mInputElements[ct].get(), mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
- }
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
- }
- }
- createShader(rsc);
-}
-
void ProgramVertex::serialize(OStream *stream) const {
}
@@ -257,7 +189,8 @@ void ProgramVertexState::init(Context *rsc) {
ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(),
shaderString.length(), tmp, 4);
- Allocation *alloc = new Allocation(rsc, inputType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
+ Allocation *alloc = Allocation::createAllocation(rsc, inputType,
+ RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
pv->bindAllocation(rsc, alloc, 0);
mDefaultAlloc.set(alloc);
@@ -269,7 +202,7 @@ void ProgramVertexState::init(Context *rsc) {
void ProgramVertexState::updateSize(Context *rsc) {
float *f = static_cast<float *>(mDefaultAlloc->getPtr());
- Matrix m;
+ Matrix4x4 m;
m.loadOrtho(0,rsc->getWidth(), rsc->getHeight(),0, -1,1);
memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m.m, sizeof(m));
memcpy(&f[RS_PROGRAM_VERTEX_MVP_OFFSET], m.m, sizeof(m));
@@ -290,8 +223,8 @@ namespace android {
namespace renderscript {
RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, const char * shaderText,
- uint32_t shaderLength, const uint32_t * params,
- uint32_t paramLength) {
+ size_t shaderLength, const uint32_t * params,
+ size_t paramLength) {
ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength, params, paramLength);
pv->incUserRef();
return pv;
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
index 2a5c863..5cfdd8b 100644
--- a/libs/rs/rsProgramVertex.h
+++ b/libs/rs/rsProgramVertex.h
@@ -31,7 +31,7 @@ public:
const uint32_t * params, uint32_t paramLength);
virtual ~ProgramVertex();
- virtual void setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc);
+ virtual void setup(Context *rsc, ProgramVertexState *state);
void setProjectionMatrix(Context *, const rsc_Matrix *) const;
void getProjectionMatrix(Context *, rsc_Matrix *) const;
@@ -40,10 +40,6 @@ public:
void transformToScreen(Context *, float *v4out, const float *v3in) const;
- virtual void createShader(Context *);
- virtual void loadShader(Context *);
- virtual void init(Context *);
-
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_VERTEX; }
static ProgramVertex *createFromStream(Context *rsc, IStream *stream);
diff --git a/libs/rs/rsRuntime.h b/libs/rs/rsRuntime.h
new file mode 100644
index 0000000..6d45285
--- /dev/null
+++ b/libs/rs/rsRuntime.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2009 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 "utils/Timers.h"
+
+#include <time.h>
+
+namespace android {
+namespace renderscript {
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Context
+//////////////////////////////////////////////////////////////////////////////
+
+void rsrBindTexture(Context *, Script *, ProgramFragment *, uint32_t slot, Allocation *);
+void rsrBindSampler(Context *, Script *, ProgramFragment *, uint32_t slot, Sampler *);
+void rsrBindProgramStore(Context *, Script *, ProgramStore *);
+void rsrBindProgramFragment(Context *, Script *, ProgramFragment *);
+void rsrBindProgramVertex(Context *, Script *, ProgramVertex *);
+void rsrBindProgramRaster(Context *, Script *, ProgramRaster *);
+void rsrBindFrameBufferObjectColorTarget(Context *, Script *, Allocation *, uint32_t slot);
+void rsrBindFrameBufferObjectDepthTarget(Context *, Script *, Allocation *);
+void rsrClearFrameBufferObjectColorTarget(Context *, Script *, uint32_t slot);
+void rsrClearFrameBufferObjectDepthTarget(Context *, Script *);
+void rsrClearFrameBufferObjectTargets(Context *, Script *);
+
+//////////////////////////////////////////////////////////////////////////////
+// VP
+//////////////////////////////////////////////////////////////////////////////
+
+void rsrVpLoadProjectionMatrix(Context *, Script *, const rsc_Matrix *m);
+void rsrVpLoadModelMatrix(Context *, Script *, const rsc_Matrix *m);
+void rsrVpLoadTextureMatrix(Context *, Script *, const rsc_Matrix *m);
+void rsrPfConstantColor(Context *, Script *, ProgramFragment *, float r, float g, float b, float a);
+void rsrVpGetProjectionMatrix(Context *, Script *, rsc_Matrix *m);
+
+//////////////////////////////////////////////////////////////////////////////
+// Drawing
+//////////////////////////////////////////////////////////////////////////////
+
+void rsrDrawQuadTexCoords(Context *, Script *,
+ 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);
+void rsrDrawQuad(Context *, Script *,
+ float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ float x3, float y3, float z3,
+ float x4, float y4, float z4);
+void rsrDrawSpriteScreenspace(Context *, Script *,
+ float x, float y, float z, float w, float h);
+void rsrDrawRect(Context *, Script *, float x1, float y1, float x2, float y2, float z);
+void rsrDrawMesh(Context *, Script *, Mesh *);
+void rsrDrawMeshPrimitive(Context *, Script *, Mesh *, uint32_t primIndex);
+void rsrDrawMeshPrimitiveRange(Context *, Script *, Mesh *,
+ uint32_t primIndex, uint32_t start, uint32_t len);
+void rsrMeshComputeBoundingBox(Context *, Script *, Mesh *,
+ float *minX, float *minY, float *minZ,
+ float *maxX, float *maxY, float *maxZ);
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+void rsrColor(Context *, Script *, float r, float g, float b, float a);
+void rsrFinish(Context *, Script *);
+void rsrAllocationSyncAll(Context *, Script *, Allocation *);
+void rsrClearColor(Context *, Script *, float r, float g, float b, float a);
+void rsrClearDepth(Context *, Script *, float v);
+uint32_t rsrGetWidth(Context *, Script *);
+uint32_t rsrGetHeight(Context *, Script *);
+void rsrDrawTextAlloc(Context *, Script *, Allocation *, int x, int y);
+void rsrDrawText(Context *, Script *, const char *text, int x, int y);
+void rsrSetMetrics(Context *, Script *, Font::Rect *metrics,
+ int32_t *left, int32_t *right, int32_t *top, int32_t *bottom);
+void rsrMeasureTextAlloc(Context *, Script *, Allocation *,
+ int32_t *left, int32_t *right, int32_t *top, int32_t *bottom);
+void rsrMeasureText(Context *, Script *, const char *text,
+ int32_t *left, int32_t *right, int32_t *top, int32_t *bottom);
+void rsrBindFont(Context *, Script *, Font *);
+void rsrFontColor(Context *, Script *, float r, float g, float b, float a);
+
+//////////////////////////////////////////////////////////////////////////////
+// Time routines
+//////////////////////////////////////////////////////////////////////////////
+
+float rsrGetDt(Context *, Script *);
+time_t rsrTime(Context *, Script *, time_t *timer);
+tm* rsrLocalTime(Context *, Script *, tm *local, time_t *timer);
+int64_t rsrUptimeMillis(Context *, Script *);
+int64_t rsrUptimeNanos(Context *, Script *);
+
+//////////////////////////////////////////////////////////////////////////////
+// Message routines
+//////////////////////////////////////////////////////////////////////////////
+
+uint32_t rsrToClient(Context *, Script *, int cmdID, void *data, int len);
+uint32_t rsrToClientBlocking(Context *, Script *, int cmdID, void *data, int len);
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//////////////////////////////////////////////////////////////////////////////
+
+void rsrSetObject(const Context *, const Script *, ObjectBase **dst, ObjectBase * src);
+void rsrClearObject(const Context *, const Script *, ObjectBase **dst);
+bool rsrIsObject(const Context *, const Script *, const ObjectBase *src);
+
+void rsrAllocationIncRefs(const Context *, const Allocation *, void *ptr,
+ size_t elementCount, size_t startOffset);
+void rsrAllocationDecRefs(const Context *, const Allocation *, void *ptr,
+ size_t elementCount, size_t startOffset);
+
+
+uint32_t rsrToClient(Context *, Script *, int cmdID, void *data, int len);
+uint32_t rsrToClientBlocking(Context *, Script *, int cmdID, void *data, int len);
+const Allocation * rsrGetAllocation(Context *, Script *, const void *ptr);
+
+void rsrAllocationMarkDirty(Context *, Script *, RsAllocation a);
+void rsrAllocationSyncAll(Context *, Script *, Allocation *a, RsAllocationUsageType source);
+
+
+void rsrForEach(Context *, Script *, Script *target,
+ Allocation *in,
+ Allocation *out,
+ const void *usr,
+ uint32_t usrBytes,
+ const RsScriptCall *call);
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Heavy math functions
+//////////////////////////////////////////////////////////////////////////////
+
+
+void rsrMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v);
+float rsrMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col);
+void rsrMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v);
+float rsrMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col);
+void rsrMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v);
+float rsrMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col);
+void rsrMatrixLoadIdentity_4x4(rs_matrix4x4 *m);
+void rsrMatrixLoadIdentity_3x3(rs_matrix3x3 *m);
+void rsrMatrixLoadIdentity_2x2(rs_matrix2x2 *m);
+void rsrMatrixLoad_4x4_f(rs_matrix4x4 *m, const float *v);
+void rsrMatrixLoad_3x3_f(rs_matrix3x3 *m, const float *v);
+void rsrMatrixLoad_2x2_f(rs_matrix2x2 *m, const float *v);
+void rsrMatrixLoad_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *v);
+void rsrMatrixLoad_4x4_3x3(rs_matrix4x4 *m, const rs_matrix3x3 *v);
+void rsrMatrixLoad_4x4_2x2(rs_matrix4x4 *m, const rs_matrix2x2 *v);
+void rsrMatrixLoad_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *v);
+void rsrMatrixLoad_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *v);
+void rsrMatrixLoadRotate(rs_matrix4x4 *m, float rot, float x, float y, float z);
+void rsrMatrixLoadScale(rs_matrix4x4 *m, float x, float y, float z);
+void rsrMatrixLoadTranslate(rs_matrix4x4 *m, float x, float y, float z);
+void rsrMatrixLoadMultiply_4x4_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *lhs,
+ const rs_matrix4x4 *rhs);
+void rsrMatrixMultiply_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *rhs);
+void rsrMatrixLoadMultiply_3x3_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *lhs,
+ const rs_matrix3x3 *rhs);
+void rsrMatrixMultiply_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *rhs);
+void rsrMatrixLoadMultiply_2x2_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *lhs,
+ const rs_matrix2x2 *rhs);
+void rsrMatrixMultiply_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *rhs);
+void rsrMatrixRotate(rs_matrix4x4 *m, float rot, float x, float y, float z);
+void rsrMatrixScale(rs_matrix4x4 *m, float x, float y, float z);
+void rsrMatrixTranslate(rs_matrix4x4 *m, float x, float y, float z);
+void rsrMatrixLoadOrtho(rs_matrix4x4 *m, float left, float right,
+ float bottom, float top, float near, float far);
+void rsrMatrixLoadFrustum(rs_matrix4x4 *m, float left, float right,
+ float bottom, float top, float near, float far);
+void rsrMatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far);
+
+// Returns true if the matrix was successfully inversed
+bool rsrMatrixInverse_4x4(rs_matrix4x4 *m);
+// Returns true if the matrix was successfully inversed
+bool rsrMatrixInverseTranspose_4x4(rs_matrix4x4 *m);
+
+void rsrMatrixTranspose_4x4(rs_matrix4x4 *m);
+void rsrMatrixTranspose_3x3(rs_matrix3x3 *m);
+void rsrMatrixTranspose_2x2(rs_matrix2x2 *m);
+
+}
+}
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index db2383a..2a05d16 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -15,11 +15,6 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsSampler.h"
@@ -39,77 +34,18 @@ Sampler::Sampler(Context *rsc,
RsSamplerValue wrapT,
RsSamplerValue wrapR,
float aniso) : ObjectBase(rsc) {
- mMagFilter = magFilter;
- mMinFilter = minFilter;
- mWrapS = wrapS;
- mWrapT = wrapT;
- mWrapR = wrapR;
- mAniso = aniso;
+ mHal.state.magFilter = magFilter;
+ mHal.state.minFilter = minFilter;
+ mHal.state.wrapS = wrapS;
+ mHal.state.wrapT = wrapT;
+ mHal.state.wrapR = wrapR;
+ mHal.state.aniso = aniso;
+
+ mRSC->mHal.funcs.sampler.init(mRSC, this);
}
Sampler::~Sampler() {
-}
-
-void Sampler::setupGL(const Context *rsc, const Allocation *tex) {
- 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
- GLenum target = (GLenum)tex->getGLTarget();
-
- if (!rsc->ext_OES_texture_npot() && tex->getType()->getIsNp2()) {
- if (tex->getHasGraphicsMipmaps() &&
- (rsc->ext_GL_NV_texture_npot_2D_mipmap() || rsc->ext_GL_IMG_texture_npot())) {
- if (rsc->ext_GL_NV_texture_npot_2D_mipmap()) {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
- } else {
- switch (trans[mMinFilter]) {
- case GL_LINEAR_MIPMAP_LINEAR:
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
- break;
- default:
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
- break;
- }
- }
- } else {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
- }
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, transNP[mMagFilter]);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, transNP[mWrapS]);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, transNP[mWrapT]);
- } else {
- if (tex->getHasGraphicsMipmaps()) {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
- } else {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
- }
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, trans[mMagFilter]);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, trans[mWrapS]);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, trans[mWrapT]);
- }
-
- float anisoValue = rsMin(rsc->ext_texture_max_aniso(), mAniso);
- if (rsc->ext_texture_max_aniso() > 1.0f) {
- glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
- }
-
- rsc->checkError("Sampler::setupGL2 tex env");
+ mRSC->mHal.funcs.sampler.destroy(mRSC, this);
}
void Sampler::bindToContext(SamplerState *ss, uint32_t slot) {
@@ -135,66 +71,14 @@ Sampler *Sampler::createFromStream(Context *rsc, IStream *stream) {
namespace android {
namespace renderscript {
-
-void rsi_SamplerBegin(Context *rsc) {
- SamplerState * ss = &rsc->mStateSampler;
-
- ss->mMagFilter = RS_SAMPLER_LINEAR;
- ss->mMinFilter = RS_SAMPLER_LINEAR;
- ss->mWrapS = RS_SAMPLER_WRAP;
- ss->mWrapT = RS_SAMPLER_WRAP;
- ss->mWrapR = RS_SAMPLER_WRAP;
- ss->mAniso = 1.0f;
-}
-
-void rsi_SamplerSet(Context *rsc, RsSamplerParam param, RsSamplerValue value) {
- SamplerState * ss = &rsc->mStateSampler;
-
- switch (param) {
- case RS_SAMPLER_MAG_FILTER:
- ss->mMagFilter = value;
- break;
- case RS_SAMPLER_MIN_FILTER:
- ss->mMinFilter = value;
- break;
- case RS_SAMPLER_WRAP_S:
- ss->mWrapS = value;
- break;
- case RS_SAMPLER_WRAP_T:
- ss->mWrapT = value;
- break;
- case RS_SAMPLER_WRAP_R:
- ss->mWrapR = value;
- break;
- default:
- LOGE("Attempting to set invalid value on sampler");
- break;
- }
-}
-
-void rsi_SamplerSet2(Context *rsc, RsSamplerParam param, float value) {
- SamplerState * ss = &rsc->mStateSampler;
-
- switch (param) {
- case RS_SAMPLER_ANISO:
- ss->mAniso = value;
- break;
- default:
- LOGE("Attempting to set invalid value on sampler");
- break;
- }
-}
-
-RsSampler rsi_SamplerCreate(Context *rsc) {
- SamplerState * ss = &rsc->mStateSampler;
-
- Sampler * s = new Sampler(rsc,
- ss->mMagFilter,
- ss->mMinFilter,
- ss->mWrapS,
- ss->mWrapT,
- ss->mWrapR,
- ss->mAniso);
+RsSampler rsi_SamplerCreate(Context * rsc,
+ RsSamplerValue magFilter,
+ RsSamplerValue minFilter,
+ RsSamplerValue wrapS,
+ RsSamplerValue wrapT,
+ RsSamplerValue wrapR,
+ float aniso) {
+ Sampler * s = new Sampler(rsc, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
s->incUserRef();
return s;
}
diff --git a/libs/rs/rsSampler.h b/libs/rs/rsSampler.h
index 737bb8b..90b6082 100644
--- a/libs/rs/rsSampler.h
+++ b/libs/rs/rsSampler.h
@@ -40,9 +40,6 @@ public:
virtual ~Sampler();
- void bind(Allocation *);
- void setupGL(const Context *, const Allocation *);
-
void bindToContext(SamplerState *, uint32_t slot);
void unbindFromContext(SamplerState *);
@@ -50,14 +47,22 @@ public:
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_SAMPLER; }
static Sampler *createFromStream(Context *rsc, IStream *stream);
-protected:
- RsSamplerValue mMagFilter;
- RsSamplerValue mMinFilter;
- RsSamplerValue mWrapS;
- RsSamplerValue mWrapT;
- RsSamplerValue mWrapR;
- float mAniso;
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ RsSamplerValue magFilter;
+ RsSamplerValue minFilter;
+ RsSamplerValue wrapS;
+ RsSamplerValue wrapT;
+ RsSamplerValue wrapR;
+ float aniso;
+ };
+ State state;
+ };
+ Hal mHal;
+protected:
int32_t mBoundSlot;
private:
@@ -67,13 +72,6 @@ private:
class SamplerState {
public:
- RsSamplerValue mMagFilter;
- RsSamplerValue mMinFilter;
- RsSamplerValue mWrapS;
- RsSamplerValue mWrapT;
- RsSamplerValue mWrapR;
- float mAniso;
-
ObjectBaseRef<Sampler> mSamplers[RS_MAX_SAMPLER_SLOT];
};
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index afee2a3..f62c72e 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -21,6 +21,7 @@ using namespace android::renderscript;
Script::Script(Context *rsc) : ObjectBase(rsc) {
memset(&mEnviroment, 0, sizeof(mEnviroment));
+ memset(&mHal, 0, sizeof(mHal));
mSlots = NULL;
mTypes = NULL;
@@ -37,48 +38,38 @@ Script::~Script() {
}
}
-void Script::initSlots() {
- if (mEnviroment.mFieldCount > 0) {
- mSlots = new ObjectBaseRef<Allocation>[mEnviroment.mFieldCount];
- mTypes = new ObjectBaseRef<const Type>[mEnviroment.mFieldCount];
- }
-}
-
void Script::setSlot(uint32_t slot, Allocation *a) {
- if (slot >= mEnviroment.mFieldCount) {
+ //LOGE("setSlot %i %p", slot, a);
+ if (slot >= mHal.info.exportedVariableCount) {
LOGE("Script::setSlot unable to set allocation, invalid slot index");
return;
}
mSlots[slot].set(a);
+ if (a != NULL) {
+ mRSC->mHal.funcs.script.setGlobalBind(mRSC, this, slot, a->getPtr());
+ } else {
+ mRSC->mHal.funcs.script.setGlobalBind(mRSC, this, slot, NULL);
+ }
}
-void Script::setVar(uint32_t slot, const void *val, uint32_t len) {
- int32_t *destPtr = ((int32_t **)mEnviroment.mFieldAddress)[slot];
- if (destPtr) {
- //LOGE("setVar f1 %f", ((const float *)destPtr)[0]);
- //LOGE("setVar %p %i", destPtr, len);
- memcpy(destPtr, val, len);
- //LOGE("setVar f2 %f", ((const float *)destPtr)[0]);
- } else {
- //if (rsc->props.mLogScripts) {
- LOGV("Calling setVar on slot = %i which is null", slot);
- //}
+void Script::setVar(uint32_t slot, const void *val, size_t len) {
+ //LOGE("setVar %i %p %i", slot, val, len);
+ if (slot >= mHal.info.exportedVariableCount) {
+ LOGE("Script::setVar unable to set allocation, invalid slot index");
+ return;
}
+ mRSC->mHal.funcs.script.setGlobalVar(mRSC, this, slot, (void *)val, len);
}
void Script::setVarObj(uint32_t slot, ObjectBase *val) {
- ObjectBase **destPtr = ((ObjectBase ***)mEnviroment.mFieldAddress)[slot];
-
- if (destPtr) {
- if (val != NULL) {
- val->incSysRef();
- }
- if (*destPtr) {
- (*destPtr)->decSysRef();
- }
- *destPtr = val;
+ //LOGE("setVarObj %i %p", slot, val);
+ if (slot >= mHal.info.exportedVariableCount) {
+ LOGE("Script::setVarObj unable to set allocation, invalid slot index");
+ return;
}
+ //LOGE("setvarobj %i %p", slot, val);
+ mRSC->mHal.funcs.script.setGlobalObj(mRSC, this, slot, val);
}
namespace android {
@@ -91,11 +82,21 @@ void rsi_ScriptBindAllocation(Context * rsc, RsScript vs, RsAllocation va, uint3
//LOGE("rsi_ScriptBindAllocation %i %p %p", slot, a, a->getPtr());
}
-void rsi_ScriptSetTimeZone(Context * rsc, RsScript vs, const char * timeZone, uint32_t length) {
+void rsi_ScriptSetTimeZone(Context * rsc, RsScript vs, const char * timeZone, size_t length) {
Script *s = static_cast<Script *>(vs);
s->mEnviroment.mTimeZone = timeZone;
}
+void rsi_ScriptForEach(Context *rsc, RsScript vs, uint32_t slot,
+ RsAllocation vain, RsAllocation vaout,
+ const void *params, size_t paramLen) {
+ Script *s = static_cast<Script *>(vs);
+ s->runForEach(rsc,
+ static_cast<const Allocation *>(vain), static_cast<Allocation *>(vaout),
+ params, paramLen);
+
+}
+
void rsi_ScriptInvoke(Context *rsc, RsScript vs, uint32_t slot) {
Script *s = static_cast<Script *>(vs);
s->Invoke(rsc, slot, NULL, 0);
@@ -107,7 +108,7 @@ void rsi_ScriptInvokeData(Context *rsc, RsScript vs, uint32_t slot, void *data)
s->Invoke(rsc, slot, NULL, 0);
}
-void rsi_ScriptInvokeV(Context *rsc, RsScript vs, uint32_t slot, const void *data, uint32_t len) {
+void rsi_ScriptInvokeV(Context *rsc, RsScript vs, uint32_t slot, const void *data, size_t len) {
Script *s = static_cast<Script *>(vs);
s->Invoke(rsc, slot, data, len);
}
@@ -138,7 +139,7 @@ void rsi_ScriptSetVarD(Context *rsc, RsScript vs, uint32_t slot, double value) {
s->setVar(slot, &value, sizeof(value));
}
-void rsi_ScriptSetVarV(Context *rsc, RsScript vs, uint32_t slot, const void *data, uint32_t len) {
+void rsi_ScriptSetVarV(Context *rsc, RsScript vs, uint32_t slot, const void *data, size_t len) {
Script *s = static_cast<Script *>(vs);
s->setVar(slot, data, len);
}
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index bad095b..c0324dd 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -31,6 +31,26 @@ class ProgramStore;
class Script : public ObjectBase {
public:
+ struct Hal {
+ void * drv;
+
+ struct DriverInfo {
+ int mVersionMajor;
+ int mVersionMinor;
+
+ size_t exportedVariableCount;
+ size_t exportedFunctionCount;
+ size_t exportedPragmaCount;
+ char const **exportedPragmaKeyList;
+ char const **exportedPragmaValueList;
+
+ int (* root)();
+ bool isThreadable;
+ };
+ DriverInfo info;
+ };
+ Hal mHal;
+
typedef void (* InvokeFunc_t)(void);
Script(Context *);
@@ -45,31 +65,22 @@ public:
ObjectBaseRef<ProgramFragment> mFragment;
ObjectBaseRef<ProgramRaster> mRaster;
ObjectBaseRef<ProgramStore> mFragmentStore;
-
- uint32_t mInvokeFunctionCount;
- InvokeFunc_t *mInvokeFunctions;
- uint32_t mFieldCount;
- void ** mFieldAddress;
-
- char * mScriptText;
- uint32_t mScriptTextLength;
-
- bool mIsThreadable;
};
Enviroment_t mEnviroment;
void initSlots();
void setSlot(uint32_t slot, Allocation *a);
- void setVar(uint32_t slot, const void *val, uint32_t len);
+ void setVar(uint32_t slot, const void *val, size_t len);
void setVarObj(uint32_t slot, ObjectBase *val);
virtual void runForEach(Context *rsc,
const Allocation * ain,
Allocation * aout,
const void * usr,
+ size_t usrBytes,
const RsScriptCall *sc = NULL) = 0;
- virtual void Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) = 0;
+ virtual void Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) = 0;
virtual void setupScript(Context *rsc) = 0;
virtual uint32_t run(Context *) = 0;
protected:
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index e12926b..b230bb5 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -16,17 +16,8 @@
#include "rsContext.h"
#include "rsScriptC.h"
-#include "rsMatrix.h"
#include "utils/Timers.h"
#include "utils/StopWatch.h"
-extern "C" {
-#include "libdex/ZipArchive.h"
-}
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <bcc/bcc.h>
using namespace android;
using namespace android::renderscript;
@@ -36,94 +27,18 @@ using namespace android::renderscript;
Context * rsc = tls->mContext; \
ScriptC * sc = (ScriptC *) tls->mScript
-// Input: cacheDir
-// Input: resName
-// Input: extName
-//
-// Note: cacheFile = resName + extName
-//
-// Output: Returns cachePath == cacheDir + cacheFile
-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);
-}
-
ScriptC::ScriptC(Context *rsc) : Script(rsc) {
- mBccScript = NULL;
- memset(&mProgram, 0, sizeof(mProgram));
}
ScriptC::~ScriptC() {
- if (mBccScript) {
- if (mProgram.mObjectSlotList) {
- for (size_t ct=0; ct < mProgram.mObjectSlotCount; ct++) {
- setVarObj(mProgram.mObjectSlotList[ct], NULL);
- }
- delete [] mProgram.mObjectSlotList;
- mProgram.mObjectSlotList = NULL;
- mProgram.mObjectSlotCount = 0;
- }
-
-
- LOGD(">>>> ~ScriptC bccDisposeScript(%p)", mBccScript);
- bccDisposeScript(mBccScript);
- }
- free(mEnviroment.mScriptText);
- mEnviroment.mScriptText = NULL;
+ mRSC->mHal.funcs.script.destroy(mRSC, this);
}
void ScriptC::setupScript(Context *rsc) {
mEnviroment.mStartTimeMillis
= nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
- for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
+ for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
if (mSlots[ct].get() && !mTypes[ct].get()) {
mTypes[ct].set(mSlots[ct]->getType());
}
@@ -134,27 +49,17 @@ void ScriptC::setupScript(Context *rsc) {
if (mSlots[ct].get()) {
ptr = mSlots[ct]->getPtr();
}
- void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
- if (rsc->props.mLogScripts) {
- if (mSlots[ct].get() != NULL) {
- LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=%p", rsc, ct, dest, ptr, mSlots[ct]->getType());
- } else {
- LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=null", rsc, ct, dest, ptr);
- }
- }
-
- if (dest) {
- *dest = ptr;
- }
+ rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, ptr);
}
}
const Allocation *ScriptC::ptrToAllocation(const void *ptr) const {
+ //LOGE("ptr to alloc %p", ptr);
if (!ptr) {
return NULL;
}
- for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
+ for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
if (!mSlots[ct].get())
continue;
if (mSlots[ct]->getPtr() == ptr) {
@@ -165,15 +70,6 @@ const Allocation *ScriptC::ptrToAllocation(const void *ptr) const {
return NULL;
}
-Script * ScriptC::setTLS(Script *sc) {
- Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *)
- pthread_getspecific(Context::gThreadTLSKey);
- rsAssert(tls);
- Script *old = tls->mScript;
- tls->mScript = sc;
- return old;
-}
-
void ScriptC::setupGLState(Context *rsc) {
if (mEnviroment.mFragmentStore.get()) {
rsc->setProgramStore(mEnviroment.mFragmentStore.get());
@@ -190,7 +86,7 @@ void ScriptC::setupGLState(Context *rsc) {
}
uint32_t ScriptC::run(Context *rsc) {
- if (mProgram.mRoot == NULL) {
+ if (mHal.info.root == NULL) {
rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
return 0;
}
@@ -199,235 +95,46 @@ uint32_t ScriptC::run(Context *rsc) {
setupScript(rsc);
uint32_t ret = 0;
- Script * oldTLS = setTLS(this);
if (rsc->props.mLogScripts) {
- LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mProgram.mRoot);
+ LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mHal.info.root);
}
- ret = mProgram.mRoot();
+ ret = rsc->mHal.funcs.script.invokeRoot(rsc, this);
if (rsc->props.mLogScripts) {
LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
}
- setTLS(oldTLS);
return ret;
}
-typedef struct {
- Context *rsc;
- ScriptC *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->mProgram.mRoot) (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->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0);
- xPtrIn += mtls->eStrideIn;
- xPtrOut += mtls->eStrideOut;
- }
- }
-}
void ScriptC::runForEach(Context *rsc,
const Allocation * ain,
Allocation * aout,
const void * usr,
+ size_t usrBytes,
const RsScriptCall *sc) {
- MTLaunchStruct mtls;
- memset(&mtls, 0, sizeof(mtls));
- Context::PushState ps(rsc);
- 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->getType()->getDimZ() == 0);
+ Context::PushState ps(rsc);
setupGLState(rsc);
setupScript(rsc);
- Script * oldTLS = setTLS(this);
-
- mtls.rsc = rsc;
- mtls.ain = ain;
- mtls.aout = aout;
- mtls.script = this;
- 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 ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable) {
- if (mtls.dimY > 1) {
- rsc->launchThreads(wc_xy, &mtls);
- } else {
- rsc->launchThreads(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)mProgram.mRoot) (xPtrIn, xPtrOut, usr, x, y, z, ar);
- xPtrIn += mtls.eStrideIn;
- xPtrOut += mtls.eStrideOut;
- }
- }
- }
- }
- }
-
- setTLS(oldTLS);
+ rsc->mHal.funcs.script.invokeForEach(rsc, this, ain, aout, usr, usrBytes, sc);
}
-void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) {
- if ((slot >= mEnviroment.mInvokeFunctionCount) ||
- (mEnviroment.mInvokeFunctions[slot] == NULL)) {
+void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) {
+ if (slot >= mHal.info.exportedFunctionCount) {
rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
return;
}
setupScript(rsc);
- Script * oldTLS = setTLS(this);
if (rsc->props.mLogScripts) {
- LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, mEnviroment.mInvokeFunctions[slot]);
- }
- ((void (*)(const void *, uint32_t))
- mEnviroment.mInvokeFunctions[slot])(data, len);
- if (rsc->props.mLogScripts) {
- LOGV("%p ScriptC::Invoke complete", rsc);
+ LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, this);
}
-
- setTLS(oldTLS);
+ rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len);
}
ScriptCState::ScriptCState() {
@@ -436,13 +143,14 @@ ScriptCState::ScriptCState() {
ScriptCState::~ScriptCState() {
}
+/*
static void* symbolLookup(void* pContext, char const* name) {
const ScriptCState::SymbolTable_t *sym;
ScriptC *s = (ScriptC *)pContext;
if (!strcmp(name, "__isThreadable")) {
- return (void*) s->mEnviroment.mIsThreadable;
+ return (void*) s->mHal.info.isThreadable;
} else if (!strcmp(name, "__clearThreadable")) {
- s->mEnviroment.mIsThreadable = false;
+ s->mHal.info.isThreadable = false;
return NULL;
}
sym = ScriptCState::lookupSymbol(name);
@@ -453,156 +161,99 @@ static void* symbolLookup(void* pContext, char const* name) {
sym = ScriptCState::lookupSymbolGL(name);
}
if (sym) {
- s->mEnviroment.mIsThreadable &= sym->threadable;
+ s->mHal.info.isThreadable &= sym->threadable;
return sym->mPtr;
}
LOGE("ScriptC sym lookup failed for %s", name);
return NULL;
}
+*/
#if 0
extern const char rs_runtime_lib_bc[];
extern unsigned rs_runtime_lib_bc_size;
#endif
-bool ScriptCState::runCompiler(Context *rsc,
- ScriptC *s,
- const char *resName,
- const char *cacheDir) {
- s->mBccScript = bccCreateScript();
-
- s->mEnviroment.mIsThreadable = true;
-
- if (bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s) != 0) {
- LOGE("bcc: FAILS to register symbol callback");
- return false;
- }
-
- if (bccReadBC(s->mBccScript,
- resName,
- s->mEnviroment.mScriptText,
- s->mEnviroment.mScriptTextLength, 0) != 0) {
- LOGE("bcc: FAILS to read bitcode");
- return false;
- }
-
-#if 1
- if (bccLinkFile(s->mBccScript, "/system/lib/libclcore.bc", 0) != 0) {
- LOGE("bcc: FAILS to link bitcode");
- return false;
- }
-#endif
- char *cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
-
- if (bccPrepareExecutable(s->mBccScript, cachePath, 0) != 0) {
- LOGE("bcc: FAILS to prepare executable");
- return false;
- }
-
- free(cachePath);
+bool ScriptC::runCompiler(Context *rsc,
+ const char *resName,
+ const char *cacheDir,
+ const uint8_t *bitcode,
+ size_t bitcodeLen) {
- s->mProgram.mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(s->mBccScript, "root"));
- s->mProgram.mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(s->mBccScript, "init"));
+ //LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
- if (s->mProgram.mInit) {
- s->mProgram.mInit();
- }
-
- s->mEnviroment.mInvokeFunctionCount = bccGetExportFuncCount(s->mBccScript);
- if (s->mEnviroment.mInvokeFunctionCount <= 0)
- s->mEnviroment.mInvokeFunctions = NULL;
- else {
- s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t*) calloc(s->mEnviroment.mInvokeFunctionCount, sizeof(Script::InvokeFunc_t));
- bccGetExportFuncList(s->mBccScript, s->mEnviroment.mInvokeFunctionCount, (void **) s->mEnviroment.mInvokeFunctions);
- }
-
- s->mEnviroment.mFieldCount = bccGetExportVarCount(s->mBccScript);
- if (s->mEnviroment.mFieldCount <= 0)
- s->mEnviroment.mFieldAddress = NULL;
- else {
- s->mEnviroment.mFieldAddress = (void **) calloc(s->mEnviroment.mFieldCount, sizeof(void *));
- bccGetExportVarList(s->mBccScript, s->mEnviroment.mFieldCount, (void **) s->mEnviroment.mFieldAddress);
- s->initSlots();
- }
+ rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0);
- s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
- s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
- s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
- s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
+ mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
+ mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
+ mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
+ mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
- const static int pragmaMax = 16;
- size_t pragmaCount = bccGetPragmaCount(s->mBccScript);
- char const *keys[pragmaMax];
- char const *values[pragmaMax];
- bccGetPragmaList(s->mBccScript, pragmaMax, keys, values);
+ rsc->mHal.funcs.script.invokeInit(rsc, this);
- for (size_t i=0; i < pragmaCount; ++i) {
+ for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) {
+ const char * key = mHal.info.exportedPragmaKeyList[i];
+ const char * value = mHal.info.exportedPragmaValueList[i];
//LOGE("pragma %s %s", keys[i], values[i]);
- if (!strcmp(keys[i], "version")) {
- if (!strcmp(values[i], "1")) {
+ if (!strcmp(key, "version")) {
+ if (!strcmp(value, "1")) {
continue;
}
- LOGE("Invalid version pragma value: %s\n", values[i]);
+ LOGE("Invalid version pragma value: %s\n", value);
return false;
}
- if (!strcmp(keys[i], "stateVertex")) {
- if (!strcmp(values[i], "default")) {
+ if (!strcmp(key, "stateVertex")) {
+ if (!strcmp(value, "default")) {
continue;
}
- if (!strcmp(values[i], "parent")) {
- s->mEnviroment.mVertex.clear();
+ if (!strcmp(value, "parent")) {
+ mEnviroment.mVertex.clear();
continue;
}
- LOGE("Unrecognized value %s passed to stateVertex", values[i]);
+ LOGE("Unrecognized value %s passed to stateVertex", value);
return false;
}
- if (!strcmp(keys[i], "stateRaster")) {
- if (!strcmp(values[i], "default")) {
+ if (!strcmp(key, "stateRaster")) {
+ if (!strcmp(value, "default")) {
continue;
}
- if (!strcmp(values[i], "parent")) {
- s->mEnviroment.mRaster.clear();
+ if (!strcmp(value, "parent")) {
+ mEnviroment.mRaster.clear();
continue;
}
- LOGE("Unrecognized value %s passed to stateRaster", values[i]);
+ LOGE("Unrecognized value %s passed to stateRaster", value);
return false;
}
- if (!strcmp(keys[i], "stateFragment")) {
- if (!strcmp(values[i], "default")) {
+ if (!strcmp(key, "stateFragment")) {
+ if (!strcmp(value, "default")) {
continue;
}
- if (!strcmp(values[i], "parent")) {
- s->mEnviroment.mFragment.clear();
+ if (!strcmp(value, "parent")) {
+ mEnviroment.mFragment.clear();
continue;
}
- LOGE("Unrecognized value %s passed to stateFragment", values[i]);
+ LOGE("Unrecognized value %s passed to stateFragment", value);
return false;
}
- if (!strcmp(keys[i], "stateStore")) {
- if (!strcmp(values[i], "default")) {
+ if (!strcmp(key, "stateStore")) {
+ if (!strcmp(value, "default")) {
continue;
}
- if (!strcmp(values[i], "parent")) {
- s->mEnviroment.mFragmentStore.clear();
+ if (!strcmp(value, "parent")) {
+ mEnviroment.mFragmentStore.clear();
continue;
}
- LOGE("Unrecognized value %s passed to stateStore", values[i]);
+ LOGE("Unrecognized value %s passed to stateStore", value);
return false;
}
}
- size_t objectSlotCount = bccGetObjectSlotCount(s->mBccScript);
- uint32_t *objectSlots = NULL;
- if (objectSlotCount) {
- objectSlots = new uint32_t[objectSlotCount];
- bccGetObjectSlotList(s->mBccScript, objectSlotCount, objectSlots);
- s->mProgram.mObjectSlotList = objectSlots;
- s->mProgram.mObjectSlotCount = objectSlotCount;
- }
+ mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount];
+ mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount];
return true;
}
@@ -610,39 +261,20 @@ bool ScriptCState::runCompiler(Context *rsc,
namespace android {
namespace renderscript {
-void rsi_ScriptCBegin(Context * rsc) {
-}
-
-void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) {
- ScriptCState *ss = &rsc->mScriptC;
-
- char *t = (char *)malloc(len + 1);
- memcpy(t, text, len);
- t[len] = 0;
- ss->mScriptText = t;
- ss->mScriptLen = len;
-}
-
-
RsScript rsi_ScriptCCreate(Context *rsc,
- const char *packageName /* deprecated */,
- const char *resName,
- const char *cacheDir)
+ const char *resName, size_t resName_length,
+ const char *cacheDir, size_t cacheDir_length,
+ const char *text, size_t text_length)
{
- ScriptCState *ss = &rsc->mScriptC;
-
ScriptC *s = new ScriptC(rsc);
- s->mEnviroment.mScriptText = ss->mScriptText;
- s->mEnviroment.mScriptTextLength = ss->mScriptLen;
- ss->mScriptText = NULL;
- ss->mScriptLen = 0;
- s->incUserRef();
- if (!ss->runCompiler(rsc, s, resName, cacheDir)) {
+ if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) {
// Error during compile, destroy s and return null.
delete s;
return NULL;
}
+
+ s->incUserRef();
return s;
}
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index 2c74b5b..5c191d9 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -21,7 +21,6 @@
#include "RenderScriptEnv.h"
-struct BCCOpaqueScript;
// ---------------------------------------------------------------------------
namespace android {
@@ -36,26 +35,11 @@ public:
ScriptC(Context *);
virtual ~ScriptC();
- struct Program_t {
- int mVersionMajor;
- int mVersionMinor;
-
- RunScript_t mRoot;
- VoidFunc_t mInit;
-
- uint32_t * mObjectSlotList;
- uint32_t mObjectSlotCount;
- };
-
-
- Program_t mProgram;
-
- BCCOpaqueScript *mBccScript;
const Allocation *ptrToAllocation(const void *) const;
- virtual void Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len);
+ virtual void Invoke(Context *rsc, uint32_t slot, const void *data, size_t len);
virtual uint32_t run(Context *);
@@ -63,13 +47,17 @@ public:
const Allocation * ain,
Allocation * aout,
const void * usr,
+ size_t usrBytes,
const RsScriptCall *sc = NULL);
virtual void serialize(OStream *stream) const { }
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_SCRIPT_C; }
static Type *createFromStream(Context *rsc, IStream *stream) { return NULL; }
-protected:
+ bool runCompiler(Context *rsc, const char *resName, const char *cacheDir,
+ const uint8_t *bitcode, size_t bitcodeLen);
+
+//protected:
void setupScript(Context *);
void setupGLState(Context *);
Script * setTLS(Script *);
@@ -83,8 +71,6 @@ public:
char * mScriptText;
size_t mScriptLen;
- bool runCompiler(Context *rsc, ScriptC *s, const char *resName, const char *cacheDir);
-
struct SymbolTable_t {
const char * mName;
void * mPtr;
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 8a4789a..4ee0a3e 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -16,7 +16,9 @@
#include "rsContext.h"
#include "rsScriptC.h"
-#include "rsMatrix.h"
+#include "rsMatrix4x4.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix2x2.h"
#include "utils/Timers.h"
@@ -25,10 +27,9 @@
using namespace android;
using namespace android::renderscript;
-#define GET_TLS() Context::ScriptTLSStruct * tls = \
- (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
- Context * rsc = tls->mContext; \
- ScriptC * sc = (ScriptC *) tls->mScript
+
+namespace android {
+namespace renderscript {
//////////////////////////////////////////////////////////////////////////////
@@ -73,44 +74,15 @@ static float SC_cosf_fast(float x) {
}
#endif
-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);
-}
-
//////////////////////////////////////////////////////////////////////////////
// Time routines
//////////////////////////////////////////////////////////////////////////////
-static time_t SC_time(time_t *timer) {
- GET_TLS();
+time_t rsrTime(Context *rsc, Script *sc, time_t *timer) {
return time(timer);
}
-static tm* SC_localtime(tm *local, time_t *timer) {
- GET_TLS();
+tm* rsrLocalTime(Context *rsc, Script *sc, tm *local, time_t *timer) {
if (!local) {
return NULL;
}
@@ -124,16 +96,15 @@ static tm* SC_localtime(tm *local, time_t *timer) {
return local;
}
-static int64_t SC_uptimeMillis() {
+int64_t rsrUptimeMillis(Context *rsc, Script *sc) {
return nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
}
-static int64_t SC_uptimeNanos() {
+int64_t rsrUptimeNanos(Context *rsc, Script *sc) {
return systemTime(SYSTEM_TIME_MONOTONIC);
}
-static float SC_getDt() {
- GET_TLS();
+float rsrGetDt(Context *rsc, Script *sc) {
int64_t l = sc->mEnviroment.mLastDtTime;
sc->mEnviroment.mLastDtTime = systemTime(SYSTEM_TIME_MONOTONIC);
return ((float)(sc->mEnviroment.mLastDtTime - l)) / 1.0e9;
@@ -143,883 +114,61 @@ static float SC_getDt() {
//
//////////////////////////////////////////////////////////////////////////////
-static uint32_t SC_allocGetDimX(RsAllocation va) {
- const Allocation *a = static_cast<const Allocation *>(va);
- CHECK_OBJ(a);
- //LOGE("SC_allocGetDimX a=%p type=%p", a, a->getType());
- return a->getType()->getDimX();
-}
-
-static uint32_t SC_allocGetDimY(RsAllocation va) {
- const Allocation *a = static_cast<const Allocation *>(va);
- CHECK_OBJ(a);
- return a->getType()->getDimY();
-}
-
-static uint32_t SC_allocGetDimZ(RsAllocation va) {
- const Allocation *a = static_cast<const Allocation *>(va);
- CHECK_OBJ(a);
- return a->getType()->getDimZ();
-}
-
-static uint32_t SC_allocGetDimLOD(RsAllocation va) {
- const Allocation *a = static_cast<const Allocation *>(va);
- CHECK_OBJ(a);
- return a->getType()->getDimLOD();
-}
-
-static uint32_t SC_allocGetDimFaces(RsAllocation va) {
- const Allocation *a = static_cast<const Allocation *>(va);
- CHECK_OBJ(a);
- return a->getType()->getDimFaces();
-}
-
-static const void * SC_getElementAtX(RsAllocation va, uint32_t x) {
- const Allocation *a = static_cast<const Allocation *>(va);
- CHECK_OBJ(a);
- const Type *t = a->getType();
- CHECK_OBJ(t);
- const uint8_t *p = (const uint8_t *)a->getPtr();
- return &p[t->getElementSizeBytes() * x];
-}
-
-static const void * SC_getElementAtXY(RsAllocation va, uint32_t x, uint32_t y) {
- const Allocation *a = static_cast<const Allocation *>(va);
- CHECK_OBJ(a);
- const Type *t = a->getType();
- CHECK_OBJ(t);
- const uint8_t *p = (const uint8_t *)a->getPtr();
- return &p[t->getElementSizeBytes() * (x + y*t->getDimX())];
-}
-
-static const void * SC_getElementAtXYZ(RsAllocation va, uint32_t x, uint32_t y, uint32_t z) {
- const Allocation *a = static_cast<const Allocation *>(va);
- CHECK_OBJ(a);
- const Type *t = a->getType();
- CHECK_OBJ(t);
- const uint8_t *p = (const uint8_t *)a->getPtr();
- return &p[t->getElementSizeBytes() * (x + y*t->getDimX())];
-}
-
-static void SC_setObject(void **vdst, void * vsrc) {
- //LOGE("SC_setObject %p,%p %p", vdst, *vdst, vsrc);
- if (vsrc) {
- CHECK_OBJ(vsrc);
- static_cast<ObjectBase *>(vsrc)->incSysRef();
+void rsrSetObject(const Context *rsc, const Script *sc, ObjectBase **dst, ObjectBase * src) {
+ //LOGE("rsiSetObject %p,%p %p", vdst, *vdst, vsrc);
+ if (src) {
+ CHECK_OBJ(src);
+ src->incSysRef();
}
- if (vdst[0]) {
- CHECK_OBJ(vdst[0]);
- static_cast<ObjectBase *>(vdst[0])->decSysRef();
+ if (dst[0]) {
+ CHECK_OBJ(dst[0]);
+ dst[0]->decSysRef();
}
- *vdst = vsrc;
- //LOGE("SC_setObject *");
+ *dst = src;
}
-static void SC_clearObject(void **vdst) {
- //LOGE("SC_clearObject %p,%p", vdst, *vdst);
- if (vdst[0]) {
- CHECK_OBJ(vdst[0]);
- static_cast<ObjectBase *>(vdst[0])->decSysRef();
+void rsrClearObject(const Context *rsc, const Script *sc, ObjectBase **dst) {
+ //LOGE("rsiClearObject %p,%p", vdst, *vdst);
+ if (dst[0]) {
+ CHECK_OBJ(dst[0]);
+ dst[0]->decSysRef();
}
- *vdst = NULL;
- //LOGE("SC_clearObject *");
+ *dst = NULL;
}
-static bool SC_isObject(RsAllocation vsrc) {
- return vsrc != NULL;
+bool rsrIsObject(const Context *rsc, const Script *sc, const ObjectBase *src) {
+ return src != NULL;
}
-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);
-}
-
-static uint32_t SC_toClient2(int cmdID, void *data, int len) {
- GET_TLS();
+uint32_t rsrToClient(Context *rsc, Script *sc, int cmdID, void *data, int len) {
//LOGE("SC_toClient %i %i %i", cmdID, len);
return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, false);
}
-static uint32_t SC_toClient(int cmdID) {
- GET_TLS();
- //LOGE("SC_toClient %i", cmdID);
- return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, false);
-}
-
-static uint32_t SC_toClientBlocking2(int cmdID, void *data, int len) {
- GET_TLS();
+uint32_t rsrToClientBlocking(Context *rsc, Script *sc, int cmdID, void *data, int len) {
//LOGE("SC_toClientBlocking %i %i", cmdID, len);
return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, true);
}
-static uint32_t SC_toClientBlocking(int cmdID) {
- GET_TLS();
- //LOGE("SC_toClientBlocking %i", cmdID);
- return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, true);
-}
-
-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;
-}
-
-int SC_getAllocation(const void *ptr) {
- GET_TLS();
- const Allocation *alloc = sc->ptrToAllocation(ptr);
- return (int)alloc;
-}
-void SC_allocationMarkDirty(RsAllocation a) {
- Allocation *alloc = static_cast<Allocation *>(a);
- alloc->sendDirty();
-}
-
-void SC_ForEach(RsScript vs,
- RsAllocation vin,
- RsAllocation vout,
- const void *usr) {
- GET_TLS();
- const Allocation *ain = static_cast<const Allocation *>(vin);
- Allocation *aout = static_cast<Allocation *>(vout);
- Script *s = static_cast<Script *>(vs);
- s->runForEach(rsc, ain, aout, usr);
-}
-
-void SC_ForEach2(RsScript vs,
- RsAllocation vin,
- RsAllocation vout,
- const void *usr,
+void rsrForEach(Context *rsc, Script *sc,
+ Script *target,
+ Allocation *in, Allocation *out,
+ const void *usr, uint32_t usrBytes,
const RsScriptCall *call) {
- GET_TLS();
- const Allocation *ain = static_cast<const Allocation *>(vin);
- Allocation *aout = static_cast<Allocation *>(vout);
- Script *s = static_cast<Script *>(vs);
- s->runForEach(rsc, ain, aout, usr, call);
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Heavy math functions
-//////////////////////////////////////////////////////////////////////////////
-
-typedef struct {
- float m[16];
-} rs_matrix4x4;
-
-typedef struct {
- float m[9];
-} rs_matrix3x3;
-
-typedef struct {
- float m[4];
-} rs_matrix2x2;
-
-static inline void
-rsMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v) {
- m->m[row * 4 + col] = v;
-}
-
-static inline float
-rsMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col) {
- return m->m[row * 4 + col];
-}
-
-static inline void
-rsMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v) {
- m->m[row * 3 + col] = v;
-}
-
-static inline float
-rsMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col) {
- return m->m[row * 3 + col];
-}
-
-static inline void
-rsMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v) {
- m->m[row * 2 + col] = v;
-}
-
-static inline float
-rsMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col) {
- return m->m[row * 2 + col];
-}
-
-
-static void SC_MatrixLoadIdentity_4x4(rs_matrix4x4 *m) {
- m->m[0] = 1.f;
- m->m[1] = 0.f;
- m->m[2] = 0.f;
- m->m[3] = 0.f;
- m->m[4] = 0.f;
- m->m[5] = 1.f;
- m->m[6] = 0.f;
- m->m[7] = 0.f;
- m->m[8] = 0.f;
- m->m[9] = 0.f;
- m->m[10] = 1.f;
- m->m[11] = 0.f;
- m->m[12] = 0.f;
- m->m[13] = 0.f;
- m->m[14] = 0.f;
- m->m[15] = 1.f;
-}
-
-static void SC_MatrixLoadIdentity_3x3(rs_matrix3x3 *m) {
- m->m[0] = 1.f;
- m->m[1] = 0.f;
- m->m[2] = 0.f;
- m->m[3] = 0.f;
- m->m[4] = 1.f;
- m->m[5] = 0.f;
- m->m[6] = 0.f;
- m->m[7] = 0.f;
- m->m[8] = 1.f;
-}
-
-static void SC_MatrixLoadIdentity_2x2(rs_matrix2x2 *m) {
- m->m[0] = 1.f;
- m->m[1] = 0.f;
- m->m[2] = 0.f;
- m->m[3] = 1.f;
-}
-
-static void SC_MatrixLoad_4x4_f(rs_matrix4x4 *m, const float *v) {
- m->m[0] = v[0];
- m->m[1] = v[1];
- m->m[2] = v[2];
- m->m[3] = v[3];
- m->m[4] = v[4];
- m->m[5] = v[5];
- m->m[6] = v[6];
- m->m[7] = v[7];
- m->m[8] = v[8];
- m->m[9] = v[9];
- m->m[10] = v[10];
- m->m[11] = v[11];
- m->m[12] = v[12];
- m->m[13] = v[13];
- m->m[14] = v[14];
- m->m[15] = v[15];
-}
-
-static void SC_MatrixLoad_3x3_f(rs_matrix3x3 *m, const float *v) {
- m->m[0] = v[0];
- m->m[1] = v[1];
- m->m[2] = v[2];
- m->m[3] = v[3];
- m->m[4] = v[4];
- m->m[5] = v[5];
- m->m[6] = v[6];
- m->m[7] = v[7];
- m->m[8] = v[8];
-}
-
-static void SC_MatrixLoad_2x2_f(rs_matrix2x2 *m, const float *v) {
- m->m[0] = v[0];
- m->m[1] = v[1];
- m->m[2] = v[2];
- m->m[3] = v[3];
-}
-
-static void SC_MatrixLoad_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *v) {
- m->m[0] = v->m[0];
- m->m[1] = v->m[1];
- m->m[2] = v->m[2];
- m->m[3] = v->m[3];
- m->m[4] = v->m[4];
- m->m[5] = v->m[5];
- m->m[6] = v->m[6];
- m->m[7] = v->m[7];
- m->m[8] = v->m[8];
- m->m[9] = v->m[9];
- m->m[10] = v->m[10];
- m->m[11] = v->m[11];
- m->m[12] = v->m[12];
- m->m[13] = v->m[13];
- m->m[14] = v->m[14];
- m->m[15] = v->m[15];
-}
-
-static void SC_MatrixLoad_4x4_3x3(rs_matrix4x4 *m, const rs_matrix3x3 *v) {
- m->m[0] = v->m[0];
- m->m[1] = v->m[1];
- m->m[2] = v->m[2];
- m->m[3] = 0.f;
- m->m[4] = v->m[3];
- m->m[5] = v->m[4];
- m->m[6] = v->m[5];
- m->m[7] = 0.f;
- m->m[8] = v->m[6];
- m->m[9] = v->m[7];
- m->m[10] = v->m[8];
- m->m[11] = 0.f;
- m->m[12] = 0.f;
- m->m[13] = 0.f;
- m->m[14] = 0.f;
- m->m[15] = 1.f;
-}
-
-static void SC_MatrixLoad_4x4_2x2(rs_matrix4x4 *m, const rs_matrix2x2 *v) {
- m->m[0] = v->m[0];
- m->m[1] = v->m[1];
- m->m[2] = 0.f;
- m->m[3] = 0.f;
- m->m[4] = v->m[2];
- m->m[5] = v->m[3];
- m->m[6] = 0.f;
- m->m[7] = 0.f;
- m->m[8] = 0.f;
- m->m[9] = 0.f;
- m->m[10] = 1.f;
- m->m[11] = 0.f;
- m->m[12] = 0.f;
- m->m[13] = 0.f;
- m->m[14] = 0.f;
- m->m[15] = 1.f;
-}
-
-static void SC_MatrixLoad_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *v) {
- m->m[0] = v->m[0];
- m->m[1] = v->m[1];
- m->m[2] = v->m[2];
- m->m[3] = v->m[3];
- m->m[4] = v->m[4];
- m->m[5] = v->m[5];
- m->m[6] = v->m[6];
- m->m[7] = v->m[7];
- m->m[8] = v->m[8];
-}
-
-static void SC_MatrixLoad_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *v) {
- m->m[0] = v->m[0];
- m->m[1] = v->m[1];
- m->m[2] = v->m[2];
- m->m[3] = v->m[3];
-}
-
-static void SC_MatrixLoadRotate(rs_matrix4x4 *m, float rot, float x, float y, float z) {
- float c, s;
- m->m[3] = 0;
- m->m[7] = 0;
- m->m[11]= 0;
- m->m[12]= 0;
- m->m[13]= 0;
- m->m[14]= 0;
- m->m[15]= 1;
- rot *= (float)(M_PI / 180.0f);
- c = cos(rot);
- s = sin(rot);
-
- const float len = x*x + y*y + z*z;
- if (len != 1) {
- const float recipLen = 1.f / sqrt(len);
- x *= recipLen;
- y *= recipLen;
- z *= recipLen;
- }
- const float nc = 1.0f - c;
- const float xy = x * y;
- const float yz = y * z;
- const float zx = z * x;
- const float xs = x * s;
- const float ys = y * s;
- const float zs = z * s;
- m->m[ 0] = x*x*nc + c;
- m->m[ 4] = xy*nc - zs;
- m->m[ 8] = zx*nc + ys;
- m->m[ 1] = xy*nc + zs;
- m->m[ 5] = y*y*nc + c;
- m->m[ 9] = yz*nc - xs;
- m->m[ 2] = zx*nc - ys;
- m->m[ 6] = yz*nc + xs;
- m->m[10] = z*z*nc + c;
-}
-
-static void SC_MatrixLoadScale(rs_matrix4x4 *m, float x, float y, float z) {
- SC_MatrixLoadIdentity_4x4(m);
- m->m[0] = x;
- m->m[5] = y;
- m->m[10] = z;
-}
-
-static void SC_MatrixLoadTranslate(rs_matrix4x4 *m, float x, float y, float z) {
- SC_MatrixLoadIdentity_4x4(m);
- m->m[12] = x;
- m->m[13] = y;
- m->m[14] = z;
-}
-
-static void SC_MatrixLoadMultiply_4x4_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs) {
- for (int i=0 ; i<4 ; i++) {
- float ri0 = 0;
- float ri1 = 0;
- float ri2 = 0;
- float ri3 = 0;
- for (int j=0 ; j<4 ; j++) {
- const float rhs_ij = rsMatrixGet(rhs, i,j);
- ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
- ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
- ri2 += rsMatrixGet(lhs, j, 2) * rhs_ij;
- ri3 += rsMatrixGet(lhs, j, 3) * rhs_ij;
- }
- rsMatrixSet(m, i, 0, ri0);
- rsMatrixSet(m, i, 1, ri1);
- rsMatrixSet(m, i, 2, ri2);
- rsMatrixSet(m, i, 3, ri3);
- }
-}
-
-static void SC_MatrixMultiply_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *rhs) {
- rs_matrix4x4 mt;
- SC_MatrixLoadMultiply_4x4_4x4_4x4(&mt, m, rhs);
- SC_MatrixLoad_4x4_4x4(m, &mt);
-}
-
-static void SC_MatrixLoadMultiply_3x3_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs) {
- for (int i=0 ; i<3 ; i++) {
- float ri0 = 0;
- float ri1 = 0;
- float ri2 = 0;
- for (int j=0 ; j<3 ; j++) {
- const float rhs_ij = rsMatrixGet(rhs, i,j);
- ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
- ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
- ri2 += rsMatrixGet(lhs, j, 2) * rhs_ij;
- }
- rsMatrixSet(m, i, 0, ri0);
- rsMatrixSet(m, i, 1, ri1);
- rsMatrixSet(m, i, 2, ri2);
- }
-}
-
-static void SC_MatrixMultiply_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *rhs) {
- rs_matrix3x3 mt;
- SC_MatrixLoadMultiply_3x3_3x3_3x3(&mt, m, rhs);
- SC_MatrixLoad_3x3_3x3(m, &mt);
-}
-
-static void SC_MatrixLoadMultiply_2x2_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs) {
- for (int i=0 ; i<2 ; i++) {
- float ri0 = 0;
- float ri1 = 0;
- for (int j=0 ; j<2 ; j++) {
- const float rhs_ij = rsMatrixGet(rhs, i,j);
- ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
- ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
- }
- rsMatrixSet(m, i, 0, ri0);
- rsMatrixSet(m, i, 1, ri1);
- }
-}
-
-static void SC_MatrixMultiply_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *rhs) {
- rs_matrix2x2 mt;
- SC_MatrixLoadMultiply_2x2_2x2_2x2(&mt, m, rhs);
- SC_MatrixLoad_2x2_2x2(m, &mt);
-}
-
-static void SC_MatrixRotate(rs_matrix4x4 *m, float rot, float x, float y, float z) {
- rs_matrix4x4 m1;
- SC_MatrixLoadRotate(&m1, rot, x, y, z);
- SC_MatrixMultiply_4x4_4x4(m, &m1);
-}
-
-static void SC_MatrixScale(rs_matrix4x4 *m, float x, float y, float z) {
- rs_matrix4x4 m1;
- SC_MatrixLoadScale(&m1, x, y, z);
- SC_MatrixMultiply_4x4_4x4(m, &m1);
+ target->runForEach(rsc, in, out, usr, usrBytes, call);
}
-static void SC_MatrixTranslate(rs_matrix4x4 *m, float x, float y, float z) {
- rs_matrix4x4 m1;
- SC_MatrixLoadTranslate(&m1, x, y, z);
- SC_MatrixMultiply_4x4_4x4(m, &m1);
-}
-
-static void SC_MatrixLoadOrtho(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far) {
- SC_MatrixLoadIdentity_4x4(m);
- m->m[0] = 2.f / (right - left);
- m->m[5] = 2.f / (top - bottom);
- m->m[10]= -2.f / (far - near);
- m->m[12]= -(right + left) / (right - left);
- m->m[13]= -(top + bottom) / (top - bottom);
- m->m[14]= -(far + near) / (far - near);
-}
-
-static void SC_MatrixLoadFrustum(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far) {
- SC_MatrixLoadIdentity_4x4(m);
- m->m[0] = 2.f * near / (right - left);
- m->m[5] = 2.f * near / (top - bottom);
- m->m[8] = (right + left) / (right - left);
- m->m[9] = (top + bottom) / (top - bottom);
- m->m[10]= -(far + near) / (far - near);
- m->m[11]= -1.f;
- m->m[14]= -2.f * far * near / (far - near);
- m->m[15]= 0.f;
-}
-
-static void SC_MatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far) {
- float top = near * tan((float) (fovy * M_PI / 360.0f));
- float bottom = -top;
- float left = bottom * aspect;
- float right = top * aspect;
- SC_MatrixLoadFrustum(m, left, right, bottom, top, near, far);
-}
-
-
-// Returns true if the matrix was successfully inversed
-static bool SC_MatrixInverse_4x4(rs_matrix4x4 *m) {
- rs_matrix4x4 result;
-
- int i, j;
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < 4; ++j) {
- // computeCofactor for int i, int j
- int c0 = (i+1) % 4;
- int c1 = (i+2) % 4;
- int c2 = (i+3) % 4;
- int r0 = (j+1) % 4;
- int r1 = (j+2) % 4;
- int r2 = (j+3) % 4;
-
- float minor = (m->m[c0 + 4*r0] * (m->m[c1 + 4*r1] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r1]))
- - (m->m[c0 + 4*r1] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r0]))
- + (m->m[c0 + 4*r2] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r1] - m->m[c1 + 4*r1] * m->m[c2 + 4*r0]));
-
- float cofactor = (i+j) & 1 ? -minor : minor;
-
- result.m[4*i + j] = cofactor;
- }
- }
-
- // Dot product of 0th column of source and 0th row of result
- float det = m->m[0]*result.m[0] + m->m[4]*result.m[1] +
- m->m[8]*result.m[2] + m->m[12]*result.m[3];
-
- if (fabs(det) < 1e-6) {
- return false;
- }
-
- det = 1.0f / det;
- for (i = 0; i < 16; ++i) {
- m->m[i] = result.m[i] * det;
- }
-
- return true;
-}
-
-// Returns true if the matrix was successfully inversed
-static bool SC_MatrixInverseTranspose_4x4(rs_matrix4x4 *m) {
- rs_matrix4x4 result;
-
- int i, j;
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < 4; ++j) {
- // computeCofactor for int i, int j
- int c0 = (i+1) % 4;
- int c1 = (i+2) % 4;
- int c2 = (i+3) % 4;
- int r0 = (j+1) % 4;
- int r1 = (j+2) % 4;
- int r2 = (j+3) % 4;
-
- float minor = (m->m[c0 + 4*r0] * (m->m[c1 + 4*r1] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r1]))
- - (m->m[c0 + 4*r1] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r0]))
- + (m->m[c0 + 4*r2] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r1] - m->m[c1 + 4*r1] * m->m[c2 + 4*r0]));
-
- float cofactor = (i+j) & 1 ? -minor : minor;
-
- result.m[4*j + i] = cofactor;
- }
- }
-
- // Dot product of 0th column of source and 0th column of result
- float det = m->m[0]*result.m[0] + m->m[4]*result.m[4] +
- m->m[8]*result.m[8] + m->m[12]*result.m[12];
-
- if (fabs(det) < 1e-6) {
- return false;
- }
-
- det = 1.0f / det;
- for (i = 0; i < 16; ++i) {
- m->m[i] = result.m[i] * det;
- }
-
- return true;
+void rsrAllocationSyncAll(Context *rsc, Script *sc, Allocation *a, RsAllocationUsageType usage) {
+ a->syncAll(rsc, usage);
}
-static void SC_MatrixTranspose_4x4(rs_matrix4x4 *m) {
- int i, j;
- float temp;
- for (i = 0; i < 3; ++i) {
- for (j = i + 1; j < 4; ++j) {
- temp = m->m[i*4 + j];
- m->m[i*4 + j] = m->m[j*4 + i];
- m->m[j*4 + i] = temp;
- }
- }
+const Allocation * rsrGetAllocation(Context *rsc, Script *s, const void *ptr) {
+ ScriptC *sc = (ScriptC *)s;
+ return sc->ptrToAllocation(ptr);
}
-static void SC_MatrixTranspose_3x3(rs_matrix3x3 *m) {
- int i, j;
- float temp;
- for (i = 0; i < 2; ++i) {
- for (j = i + 1; j < 3; ++j) {
- temp = m->m[i*3 + j];
- m->m[i*3 + j] = m->m[j*4 + i];
- m->m[j*3 + i] = temp;
- }
- }
}
-
-static void SC_MatrixTranspose_2x2(rs_matrix2x2 *m) {
- float temp = m->m[1];
- m->m[1] = m->m[2];
- m->m[2] = temp;
}
-
-//////////////////////////////////////////////////////////////////////////////
-// 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 ScriptCState::SymbolTable_t 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 },
-
- // allocation
- { "_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 },
- { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation, true },
-
- { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX, true },
- { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY, true },
- { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ, true },
-
- { "_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 },
-
-
- { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_allocationMarkDirty, true },
-
-
- // 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 },
-
- // 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 },
-
- // 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 },
-
- { "_Z14rsSendToClienti", (void *)&SC_toClient, false },
- { "_Z14rsSendToClientiPKvj", (void *)&SC_toClient2, false },
- { "_Z22rsSendToClientBlockingi", (void *)&SC_toClientBlocking, false },
- { "_Z22rsSendToClientBlockingiPKvj", (void *)&SC_toClientBlocking2, false },
-
- // 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 },
-
- { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false },
- //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2, true },
-
-////////////////////////////////////////////////////////////////////
-
- //{ "sinf_fast", (void *)&SC_sinf_fast, true },
- //{ "cosf_fast", (void *)&SC_cosf_fast, true },
-
- { NULL, NULL, false }
-};
-
-const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym) {
- ScriptCState::SymbolTable_t *syms = gSyms;
-
- while (syms->mPtr) {
- if (!strcmp(syms->mName, sym)) {
- return syms;
- }
- syms++;
- }
- return NULL;
-}
diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp
index 15426bc..3259cb4 100644
--- a/libs/rs/rsScriptC_LibGL.cpp
+++ b/libs/rs/rsScriptC_LibGL.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -16,9 +16,14 @@
#include "rsContext.h"
#include "rsScriptC.h"
-#include "rsMatrix.h"
+#include "rsMatrix4x4.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix2x2.h"
#include "utils/Timers.h"
+#include "driver/rsdVertexArray.h"
+#include "driver/rsdShaderCache.h"
+#include "driver/rsdCore.h"
#define GL_GLEXT_PROTOTYPES
@@ -32,88 +37,90 @@
using namespace android;
using namespace android::renderscript;
-#define GET_TLS() Context::ScriptTLSStruct * tls = \
- (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
- Context * rsc = tls->mContext; \
- ScriptC * sc = (ScriptC *) tls->mScript
-
+namespace android {
+namespace renderscript {
//////////////////////////////////////////////////////////////////////////////
// Context
//////////////////////////////////////////////////////////////////////////////
-static void SC_bindTexture(RsProgramFragment vpf, uint32_t slot, RsAllocation va) {
- CHECK_OBJ_OR_NULL(va);
- CHECK_OBJ(vpf);
- GET_TLS();
- rsi_ProgramBindTexture(rsc,
- static_cast<ProgramFragment *>(vpf),
- slot,
- static_cast<Allocation *>(va));
+void rsrBindTexture(Context *rsc, Script *sc, ProgramFragment *pf, uint32_t slot, Allocation *a) {
+ CHECK_OBJ_OR_NULL(a);
+ CHECK_OBJ(pf);
+ pf->bindTexture(rsc, slot, a);
}
-static void SC_bindSampler(RsProgramFragment vpf, uint32_t slot, RsSampler vs) {
+void rsrBindSampler(Context *rsc, Script *sc, ProgramFragment *pf, uint32_t slot, Sampler *s) {
CHECK_OBJ_OR_NULL(vs);
CHECK_OBJ(vpf);
- GET_TLS();
- rsi_ProgramBindSampler(rsc,
- static_cast<ProgramFragment *>(vpf),
- slot,
- static_cast<Sampler *>(vs));
+ pf->bindSampler(rsc, slot, s);
}
-static void SC_bindProgramStore(RsProgramStore pfs) {
- CHECK_OBJ_OR_NULL(pfs);
- GET_TLS();
- rsi_ContextBindProgramStore(rsc, pfs);
+void rsrBindProgramStore(Context *rsc, Script *sc, ProgramStore *ps) {
+ CHECK_OBJ_OR_NULL(ps);
+ rsc->setProgramStore(ps);
}
-static void SC_bindProgramFragment(RsProgramFragment pf) {
+void rsrBindProgramFragment(Context *rsc, Script *sc, ProgramFragment *pf) {
CHECK_OBJ_OR_NULL(pf);
- GET_TLS();
- rsi_ContextBindProgramFragment(rsc, pf);
+ rsc->setProgramFragment(pf);
}
-static void SC_bindProgramVertex(RsProgramVertex pv) {
+void rsrBindProgramVertex(Context *rsc, Script *sc, ProgramVertex *pv) {
CHECK_OBJ_OR_NULL(pv);
- GET_TLS();
- rsi_ContextBindProgramVertex(rsc, pv);
+ rsc->setProgramVertex(pv);
}
-static void SC_bindProgramRaster(RsProgramRaster pv) {
- CHECK_OBJ_OR_NULL(pv);
- GET_TLS();
- rsi_ContextBindProgramRaster(rsc, pv);
+void rsrBindProgramRaster(Context *rsc, Script *sc, ProgramRaster *pr) {
+ CHECK_OBJ_OR_NULL(pr);
+ rsc->setProgramRaster(pr);
+}
+
+void rsrBindFrameBufferObjectColorTarget(Context *rsc, Script *sc, Allocation *a, uint32_t slot) {
+ CHECK_OBJ(va);
+ rsc->mFBOCache.bindColorTarget(rsc, a, slot);
+}
+
+void rsrBindFrameBufferObjectDepthTarget(Context *rsc, Script *sc, Allocation *a) {
+ CHECK_OBJ(va);
+ rsc->mFBOCache.bindDepthTarget(rsc, a);
+}
+
+void rsrClearFrameBufferObjectColorTarget(Context *rsc, Script *sc, uint32_t slot) {
+ rsc->mFBOCache.bindColorTarget(rsc, NULL, slot);
+}
+
+void rsrClearFrameBufferObjectDepthTarget(Context *rsc, Script *sc) {
+ rsc->mFBOCache.bindDepthTarget(rsc, NULL);
+}
+
+void rsrClearFrameBufferObjectTargets(Context *rsc, Script *sc) {
+ rsc->mFBOCache.resetAll(rsc);
}
//////////////////////////////////////////////////////////////////////////////
// VP
//////////////////////////////////////////////////////////////////////////////
-static void SC_vpLoadProjectionMatrix(const rsc_Matrix *m) {
- GET_TLS();
+void rsrVpLoadProjectionMatrix(Context *rsc, Script *sc, const rsc_Matrix *m) {
rsc->getProgramVertex()->setProjectionMatrix(rsc, m);
}
-static void SC_vpLoadModelMatrix(const rsc_Matrix *m) {
- GET_TLS();
+void rsrVpLoadModelMatrix(Context *rsc, Script *sc, const rsc_Matrix *m) {
rsc->getProgramVertex()->setModelviewMatrix(rsc, m);
}
-static void SC_vpLoadTextureMatrix(const rsc_Matrix *m) {
- GET_TLS();
+void rsrVpLoadTextureMatrix(Context *rsc, Script *sc, const rsc_Matrix *m) {
rsc->getProgramVertex()->setTextureMatrix(rsc, m);
}
-static void SC_pfConstantColor(RsProgramFragment vpf, float r, float g, float b, float a) {
- GET_TLS();
- CHECK_OBJ(vpf);
- ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
+void rsrPfConstantColor(Context *rsc, Script *sc, ProgramFragment *pf,
+ float r, float g, float b, float a) {
+ CHECK_OBJ(pf);
pf->setConstantColor(rsc, r, g, b, a);
}
-static void SC_vpGetProjectionMatrix(rsc_Matrix *m) {
- GET_TLS();
+void rsrVpGetProjectionMatrix(Context *rsc, Script *sc, rsc_Matrix *m) {
rsc->getProgramVertex()->getProjectionMatrix(rsc, m);
}
@@ -121,19 +128,20 @@ static void SC_vpGetProjectionMatrix(rsc_Matrix *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();
+void rsrDrawQuadTexCoords(Context *rsc, Script *sc,
+ 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) {
if (!rsc->setupCheck()) {
return;
}
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ if (!dc->gl.shaderCache->setup(rsc)) {
+ return;
+ }
+
//LOGE("Quad");
//LOGE("%4.2f, %4.2f, %4.2f", x1, y1, z1);
//LOGE("%4.2f, %4.2f, %4.2f", x2, y2, z2);
@@ -143,28 +151,29 @@ static void SC_drawQuadTexCoords(float x1, float y1, float z1,
float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
- VertexArray::Attrib attribs[2];
+ RsdVertexArray::Attrib attribs[2];
attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position");
attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0");
- VertexArray va(attribs, 2);
- va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
+ RsdVertexArray va(attribs, 2);
+ va.setup(rsc);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
-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) {
- SC_drawQuadTexCoords(x1, y1, z1, 0, 1,
- x2, y2, z2, 1, 1,
- x3, y3, z3, 1, 0,
- x4, y4, z4, 0, 0);
+void rsrDrawQuad(Context *rsc, Script *sc,
+ float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ float x3, float y3, float z3,
+ float x4, float y4, float z4) {
+ rsrDrawQuadTexCoords(rsc, sc, x1, y1, z1, 0, 1,
+ x2, y2, z2, 1, 1,
+ x3, y3, z3, 1, 0,
+ x4, y4, z4, 0, 0);
}
-static void SC_drawSpriteScreenspace(float x, float y, float z, float w, float h) {
- GET_TLS();
+void rsrDrawSpriteScreenspace(Context *rsc, Script *sc,
+ float x, float y, float z, float w, float h) {
ObjectBaseRef<const ProgramVertex> tmp(rsc->getProgramVertex());
rsc->setProgramVertex(rsc->getDefaultProgramVertex());
//rsc->setupCheck();
@@ -173,87 +182,48 @@ static void SC_drawSpriteScreenspace(float x, float y, float z, float w, float h
float sh = rsc->getHeight();
- SC_drawQuad(x, sh - y, z,
+ rsrDrawQuad(rsc, sc,
+ x, sh - y, z,
x+w, sh - y, z,
x+w, sh - (y+h), z,
x, sh - (y+h), z);
rsc->setProgramVertex((ProgramVertex *)tmp.get());
}
-/*
-static void SC_drawSprite(float x, float y, float z, float w, float h)
-{
- GET_TLS();
- float vin[3] = {x, y, z};
- float vout[4];
-
- //LOGE("ds in %f %f %f", x, y, z);
- rsc->getVertex()->transformToScreen(rsc, vout, vin);
- //LOGE("ds out %f %f %f %f", vout[0], vout[1], vout[2], vout[3]);
- vout[0] /= vout[3];
- vout[1] /= vout[3];
- vout[2] /= vout[3];
-
- vout[0] *= rsc->getWidth() / 2;
- vout[1] *= rsc->getHeight() / 2;
- vout[0] += rsc->getWidth() / 2;
- vout[1] += rsc->getHeight() / 2;
-
- vout[0] -= w/2;
- vout[1] -= h/2;
-
- //LOGE("ds out2 %f %f %f", vout[0], vout[1], vout[2]);
-
- // U, V, W, H
- SC_drawSpriteScreenspace(vout[0], vout[1], z, h, w);
- //rsc->setupCheck();
-}
-*/
-static void SC_drawRect(float x1, float y1,
- float x2, float y2, float z) {
+void rsrDrawRect(Context *rsc, Script *sc, float x1, float y1, float x2, float y2, float z) {
//LOGE("SC_drawRect %f,%f %f,%f %f", x1, y1, x2, y2, z);
- SC_drawQuad(x1, y2, z,
- x2, y2, z,
- x2, y1, z,
- x1, y1, z);
+ rsrDrawQuad(rsc, sc, x1, y2, z, x2, y2, z, x2, y1, z, x1, y1, z);
}
-static void SC_drawMesh(RsMesh vsm) {
- CHECK_OBJ(vsm);
- GET_TLS();
- Mesh *sm = static_cast<Mesh *>(vsm);
+void rsrDrawMesh(Context *rsc, Script *sc, Mesh *sm) {
+ CHECK_OBJ(sm);
if (!rsc->setupCheck()) {
return;
}
sm->render(rsc);
}
-static void SC_drawMeshPrimitive(RsMesh vsm, uint32_t primIndex) {
- CHECK_OBJ(vsm);
- GET_TLS();
- Mesh *sm = static_cast<Mesh *>(vsm);
+void rsrDrawMeshPrimitive(Context *rsc, Script *sc, Mesh *sm, uint32_t primIndex) {
+ CHECK_OBJ(sm);
if (!rsc->setupCheck()) {
return;
}
sm->renderPrimitive(rsc, primIndex);
}
-static void SC_drawMeshPrimitiveRange(RsMesh vsm, uint32_t primIndex, uint32_t start, uint32_t len) {
- CHECK_OBJ(vsm);
- GET_TLS();
- Mesh *sm = static_cast<Mesh *>(vsm);
+void rsrDrawMeshPrimitiveRange(Context *rsc, Script *sc, Mesh *sm, uint32_t primIndex,
+ uint32_t start, uint32_t len) {
+ CHECK_OBJ(sm);
if (!rsc->setupCheck()) {
return;
}
sm->renderPrimitiveRange(rsc, primIndex, start, len);
}
-static void SC_meshComputeBoundingBox(RsMesh vsm,
- float *minX, float *minY, float *minZ,
- float *maxX, float *maxY, float *maxZ) {
- CHECK_OBJ(vsm);
- GET_TLS();
- Mesh *sm = static_cast<Mesh *>(vsm);
+void rsrMeshComputeBoundingBox(Context *rsc, Script *sc, Mesh *sm,
+ float *minX, float *minY, float *minZ,
+ float *maxX, float *maxY, float *maxZ) {
+ CHECK_OBJ(sm);
sm->computeBBox();
*minX = sm->mBBoxMin[0];
*minY = sm->mBBoxMin[1];
@@ -269,70 +239,53 @@ static void SC_meshComputeBoundingBox(RsMesh vsm,
//////////////////////////////////////////////////////////////////////////////
-static void SC_color(float r, float g, float b, float a) {
- GET_TLS();
- ProgramFragment *pf = (ProgramFragment *)rsc->getProgramFragment();
+void rsrColor(Context *rsc, Script *sc, float r, float g, float b, float a) {
+ ProgramFragment *pf = rsc->getProgramFragment();
pf->setConstantColor(rsc, r, g, b, a);
}
-static void SC_allocationSyncAll(RsAllocation va) {
- CHECK_OBJ(va);
- GET_TLS();
- static_cast<Allocation *>(va)->syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT);
+void rsrFinish(Context *rsc, Script *sc) {
+ glFinish();
}
-#if 0
-static void SC_allocationSyncAll2(RsAllocation va, RsAllocationUsageType source) {
- CHECK_OBJ(va);
- GET_TLS();
- static_cast<Allocation *>(va)->syncAll(rsc, source);
-}
-#endif
-static void SC_ClearColor(float r, float g, float b, float a) {
- GET_TLS();
+void rsrClearColor(Context *rsc, Script *sc, float r, float g, float b, float a) {
+ rsc->mFBOCache.setup(rsc);
rsc->setupProgramStore();
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
}
-static void SC_ClearDepth(float v) {
- GET_TLS();
+void rsrClearDepth(Context *rsc, Script *sc, float v) {
+ rsc->mFBOCache.setup(rsc);
rsc->setupProgramStore();
glClearDepthf(v);
glClear(GL_DEPTH_BUFFER_BIT);
}
-static uint32_t SC_getWidth() {
- GET_TLS();
+uint32_t rsrGetWidth(Context *rsc, Script *sc) {
return rsc->getWidth();
}
-static uint32_t SC_getHeight() {
- GET_TLS();
+uint32_t rsrGetHeight(Context *rsc, Script *sc) {
return rsc->getHeight();
}
-static void SC_DrawTextAlloc(RsAllocation va, int x, int y) {
- CHECK_OBJ(va);
- GET_TLS();
- Allocation *alloc = static_cast<Allocation *>(va);
- const char *text = (const char *)alloc->getPtr();
- size_t allocSize = alloc->getType()->getSizeBytes();
+void rsrDrawTextAlloc(Context *rsc, Script *sc, Allocation *a, int x, int y) {
+ const char *text = (const char *)a->getPtr();
+ size_t allocSize = a->getType()->getSizeBytes();
rsc->mStateFont.renderText(text, allocSize, x, y);
}
-static void SC_DrawText(const char *text, int x, int y) {
- GET_TLS();
+void rsrDrawText(Context *rsc, Script *sc, const char *text, int x, int y) {
size_t textLen = strlen(text);
rsc->mStateFont.renderText(text, textLen, x, y);
}
-static void SC_setMetrics(Font::Rect *metrics,
- int32_t *left, int32_t *right,
- int32_t *top, int32_t *bottom) {
+static void SetMetrics(Font::Rect *metrics,
+ int32_t *left, int32_t *right, int32_t *top, int32_t *bottom) {
if (left) {
*left = metrics->left;
}
@@ -347,118 +300,32 @@ static void SC_setMetrics(Font::Rect *metrics,
}
}
-static void SC_MeasureTextAlloc(RsAllocation va,
- int32_t *left, int32_t *right,
- int32_t *top, int32_t *bottom) {
- CHECK_OBJ(va);
- GET_TLS();
- Allocation *alloc = static_cast<Allocation *>(va);
- const char *text = (const char *)alloc->getPtr();
- size_t textLen = alloc->getType()->getSizeBytes();
+void rsrMeasureTextAlloc(Context *rsc, Script *sc, Allocation *a,
+ int32_t *left, int32_t *right, int32_t *top, int32_t *bottom) {
+ CHECK_OBJ(a);
+ const char *text = (const char *)a->getPtr();
+ size_t textLen = a->getType()->getSizeBytes();
Font::Rect metrics;
rsc->mStateFont.measureText(text, textLen, &metrics);
- SC_setMetrics(&metrics, left, right, top, bottom);
+ SetMetrics(&metrics, 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();
+void rsrMeasureText(Context *rsc, Script *sc, const char *text,
+ int32_t *left, int32_t *right, int32_t *top, int32_t *bottom) {
size_t textLen = strlen(text);
Font::Rect metrics;
rsc->mStateFont.measureText(text, textLen, &metrics);
- SC_setMetrics(&metrics, left, right, top, bottom);
+ SetMetrics(&metrics, left, right, top, bottom);
}
-static void SC_BindFont(RsFont font) {
+void rsrBindFont(Context *rsc, Script *sc, Font *font) {
CHECK_OBJ(font);
- GET_TLS();
rsi_ContextBindFont(rsc, font);
}
-static void SC_FontColor(float r, float g, float b, float a) {
- GET_TLS();
+void rsrFontColor(Context *rsc, Script *sc, float r, float g, float b, float a) {
rsc->mStateFont.setFontColor(r, g, b, a);
}
-//////////////////////////////////////////////////////////////////////////////
-// 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 ScriptCState::SymbolTable_t gSyms[] = {
- { "_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 },
-
- { "_Z20rsgAllocationSyncAll13rs_allocation", (void *)&SC_allocationSyncAll, 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 },
-
- // misc
- { "_Z5colorffff", (void *)&SC_color, false },
-
- { NULL, NULL, false }
-};
-
-const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbolGL(const char *sym) {
- ScriptCState::SymbolTable_t *syms = gSyms;
-
- while (syms->mPtr) {
- if (!strcmp(syms->mName, sym)) {
- return syms;
- }
- syms++;
- }
- return NULL;
}
-
+}
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 6cf07de..ab164c3 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -23,16 +23,96 @@ using namespace android::renderscript;
ThreadIO::ThreadIO() {
mToCore.init(16 * 1024);
- mToClient.init(1024);
}
ThreadIO::~ThreadIO() {
}
+void ThreadIO::init(bool useSocket) {
+ mUsingSocket = useSocket;
+
+ if (mUsingSocket) {
+ mToClientSocket.init();
+ mToCoreSocket.init();
+ } else {
+ mToClient.init(1024);
+ }
+}
+
void ThreadIO::shutdown() {
+ //LOGE("shutdown 1");
mToCore.shutdown();
+ //LOGE("shutdown 2");
}
+void ThreadIO::coreFlush() {
+ //LOGE("coreFlush 1");
+ if (mUsingSocket) {
+ } else {
+ mToCore.flush();
+ }
+ //LOGE("coreFlush 2");
+}
+
+void * ThreadIO::coreHeader(uint32_t cmdID, size_t dataLen) {
+ //LOGE("coreHeader %i %i", cmdID, dataLen);
+ if (mUsingSocket) {
+ CoreCmdHeader hdr;
+ hdr.bytes = dataLen;
+ hdr.cmdID = cmdID;
+ mToCoreSocket.writeAsync(&hdr, sizeof(hdr));
+ } else {
+ mCoreCommandSize = dataLen;
+ mCoreCommandID = cmdID;
+ mCoreDataPtr = (uint8_t *)mToCore.reserve(dataLen);
+ mCoreDataBasePtr = mCoreDataPtr;
+ }
+ //LOGE("coreHeader ret %p", mCoreDataPtr);
+ return mCoreDataPtr;
+}
+
+void ThreadIO::coreData(const void *data, size_t dataLen) {
+ //LOGE("coreData %p %i", data, dataLen);
+ mToCoreSocket.writeAsync(data, dataLen);
+ //LOGE("coreData ret %p", mCoreDataPtr);
+}
+
+void ThreadIO::coreCommit() {
+ //LOGE("coreCommit %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize);
+ if (mUsingSocket) {
+ } else {
+ rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize);
+ mToCore.commit(mCoreCommandID, mCoreCommandSize);
+ }
+ //LOGE("coreCommit ret");
+}
+
+void ThreadIO::coreCommitSync() {
+ //LOGE("coreCommitSync %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize);
+ if (mUsingSocket) {
+ } else {
+ rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize);
+ mToCore.commitSync(mCoreCommandID, mCoreCommandSize);
+ }
+ //LOGE("coreCommitSync ret");
+}
+
+void ThreadIO::clientShutdown() {
+ //LOGE("coreShutdown 1");
+ mToClient.shutdown();
+ //LOGE("coreShutdown 2");
+}
+
+void ThreadIO::coreSetReturn(const void *data, size_t dataLen) {
+ rsAssert(dataLen <= sizeof(mToCoreRet));
+ memcpy(&mToCoreRet, data, dataLen);
+}
+
+void ThreadIO::coreGetReturn(void *data, size_t dataLen) {
+ memcpy(data, &mToCoreRet, dataLen);
+}
+
+
bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) {
bool ret = false;
while (!mToCore.isEmpty() || waitForCommand) {
@@ -58,10 +138,88 @@ bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) {
LOGE("playCoreCommands error con %p, cmd %i", con, cmdID);
mToCore.printDebugData();
}
- gPlaybackFuncs[cmdID](con, data);
+ gPlaybackFuncs[cmdID](con, data, cmdSize << 2);
mToCore.next();
}
return ret;
}
+RsMessageToClientType ThreadIO::getClientHeader(size_t *receiveLen, uint32_t *usrID) {
+ if (mUsingSocket) {
+ mToClientSocket.read(&mLastClientHeader, sizeof(mLastClientHeader));
+ } else {
+ size_t bytesData = 0;
+ const uint32_t *d = (const uint32_t *)mToClient.get(&mLastClientHeader.cmdID, (uint32_t*)&bytesData);
+ if (bytesData >= sizeof(uint32_t)) {
+ mLastClientHeader.userID = d[0];
+ mLastClientHeader.bytes = bytesData - sizeof(uint32_t);
+ } else {
+ mLastClientHeader.userID = 0;
+ mLastClientHeader.bytes = 0;
+ }
+ }
+ receiveLen[0] = mLastClientHeader.bytes;
+ usrID[0] = mLastClientHeader.userID;
+ return (RsMessageToClientType)mLastClientHeader.cmdID;
+}
+
+RsMessageToClientType ThreadIO::getClientPayload(void *data, size_t *receiveLen,
+ uint32_t *usrID, size_t bufferLen) {
+ receiveLen[0] = mLastClientHeader.bytes;
+ usrID[0] = mLastClientHeader.userID;
+ if (bufferLen < mLastClientHeader.bytes) {
+ return RS_MESSAGE_TO_CLIENT_RESIZE;
+ }
+ if (mUsingSocket) {
+ if (receiveLen[0]) {
+ mToClientSocket.read(data, receiveLen[0]);
+ }
+ return (RsMessageToClientType)mLastClientHeader.cmdID;
+ } else {
+ uint32_t bytesData = 0;
+ uint32_t commandID = 0;
+ const uint32_t *d = (const uint32_t *)mToClient.get(&commandID, &bytesData);
+ //LOGE("getMessageToClient 3 %i %i", commandID, bytesData);
+ //LOGE("getMessageToClient %i %i", commandID, *subID);
+ if (bufferLen >= receiveLen[0]) {
+ memcpy(data, d+1, receiveLen[0]);
+ mToClient.next();
+ return (RsMessageToClientType)commandID;
+ }
+ }
+ return RS_MESSAGE_TO_CLIENT_RESIZE;
+}
+
+bool ThreadIO::sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data,
+ size_t dataLen, bool waitForSpace) {
+ ClientCmdHeader hdr;
+ hdr.bytes = dataLen;
+ hdr.cmdID = cmdID;
+ hdr.userID = usrID;
+ if (mUsingSocket) {
+ mToClientSocket.writeAsync(&hdr, sizeof(hdr));
+ if (dataLen) {
+ mToClientSocket.writeAsync(data, dataLen);
+ }
+ return true;
+ } else {
+ if (!waitForSpace) {
+ if (!mToClient.makeSpaceNonBlocking(dataLen + sizeof(hdr))) {
+ // Not enough room, and not waiting.
+ return false;
+ }
+ }
+
+ //LOGE("sendMessageToClient 2");
+ uint32_t *p = (uint32_t *)mToClient.reserve(dataLen + sizeof(usrID));
+ p[0] = usrID;
+ if (dataLen > 0) {
+ memcpy(p+1, data, dataLen);
+ }
+ mToClient.commit(cmdID, dataLen + sizeof(usrID));
+ //LOGE("sendMessageToClient 3");
+ return true;
+ }
+ return false;
+}
diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h
index f9d0de7..cad7318 100644
--- a/libs/rs/rsThreadIO.h
+++ b/libs/rs/rsThreadIO.h
@@ -19,6 +19,7 @@
#include "rsUtils.h"
#include "rsLocklessFifo.h"
+#include "rsFifoSocket.h"
// ---------------------------------------------------------------------------
namespace android {
@@ -31,17 +32,58 @@ public:
ThreadIO();
~ThreadIO();
+ void init(bool useSocket = false);
void shutdown();
// Plays back commands from the client.
// Returns true if any commands were processed.
bool playCoreCommands(Context *con, bool waitForCommand);
+ //LocklessCommandFifo mToCore;
- LocklessCommandFifo mToCore;
+
+
+ void coreFlush();
+ void * coreHeader(uint32_t, size_t dataLen);
+ void coreData(const void *data, size_t dataLen);
+ void coreCommit();
+ void coreCommitSync();
+ void coreSetReturn(const void *data, size_t dataLen);
+ void coreGetReturn(void *data, size_t dataLen);
+
+
+ RsMessageToClientType getClientHeader(size_t *receiveLen, uint32_t *usrID);
+ RsMessageToClientType getClientPayload(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen);
+ bool sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data, size_t dataLen, bool waitForSpace);
+ void clientShutdown();
+
+
+protected:
+ typedef struct CoreCmdHeaderRec {
+ uint32_t cmdID;
+ uint32_t bytes;
+ } CoreCmdHeader;
+ typedef struct ClientCmdHeaderRec {
+ uint32_t cmdID;
+ uint32_t bytes;
+ uint32_t userID;
+ } ClientCmdHeader;
+ ClientCmdHeader mLastClientHeader;
+
+ size_t mCoreCommandSize;
+ uint32_t mCoreCommandID;
+ uint8_t * mCoreDataPtr;
+ uint8_t * mCoreDataBasePtr;
+
+ bool mUsingSocket;
LocklessCommandFifo mToClient;
+ LocklessCommandFifo mToCore;
+
+ FifoSocket mToClientSocket;
+ FifoSocket mToCoreSocket;
intptr_t mToCoreRet;
+
};
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index cd2be94..10e3182 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -274,17 +274,16 @@ Type * Type::cloneAndResize2D(Context *rsc,
namespace android {
namespace renderscript {
-}
-}
-
-RsType rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimX,
+RsType rsi_TypeCreate(Context *rsc, RsElement _e, uint32_t dimX,
uint32_t dimY, uint32_t dimZ, bool mips, bool faces) {
- Context *rsc = static_cast<Context *>(con);
Element *e = static_cast<Element *>(_e);
return Type::getType(rsc, e, dimX, dimY, dimZ, mips, faces);
}
+}
+}
+
void rsaTypeGetNativeData(RsContext con, RsType type, uint32_t *typeData, uint32_t typeDataSize) {
rsAssert(typeDataSize == 6);
// Pack the data in the follofing way mDimX; mDimY; mDimZ;
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 90ae039..086db33 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -18,7 +18,6 @@
#define ANDROID_STRUCTURED_TYPE_H
#include "rsElement.h"
-#include "rsVertexArray.h"
// ---------------------------------------------------------------------------
namespace android {
diff --git a/libs/rs/rsUtils.h b/libs/rs/rsUtils.h
index 3b60af5..3a6c85a 100644
--- a/libs/rs/rsUtils.h
+++ b/libs/rs/rsUtils.h
@@ -32,10 +32,6 @@
#include <time.h>
#include <cutils/atomic.h>
-#ifndef ANDROID_RS_SERIALIZE
-#include <EGL/egl.h>
-#endif
-
#include <math.h>
#include "RenderScript.h"
diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h
new file mode 100644
index 0000000..7bb09bb
--- /dev/null
+++ b/libs/rs/rs_hal.h
@@ -0,0 +1,176 @@
+/*
+ * 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 RS_HAL_H
+#define RS_HAL_H
+
+#include <RenderScriptDefines.h>
+
+namespace android {
+namespace renderscript {
+
+class Context;
+class ObjectBase;
+class Element;
+class Type;
+class Allocation;
+class Script;
+class ScriptC;
+class Program;
+class ProgramStore;
+class ProgramRaster;
+class ProgramVertex;
+class ProgramFragment;
+class Mesh;
+class Sampler;
+class FBOCache;
+
+typedef void *(*RsHalSymbolLookupFunc)(void *usrptr, char const *symbolName);
+
+/**
+ * Script management functions
+ */
+typedef struct {
+ bool (*initGraphics)(const Context *);
+ void (*shutdownGraphics)(const Context *);
+ bool (*setSurface)(const Context *, uint32_t w, uint32_t h, RsNativeWindow);
+ void (*swap)(const Context *);
+
+ void (*shutdownDriver)(Context *);
+ void (*getVersion)(unsigned int *major, unsigned int *minor);
+ void (*setPriority)(const Context *, int32_t priority);
+
+
+
+ struct {
+ bool (*init)(const Context *rsc, ScriptC *s,
+ char const *resName,
+ char const *cacheDir,
+ uint8_t const *bitcode,
+ size_t bitcodeSize,
+ uint32_t flags);
+
+ void (*invokeFunction)(const Context *rsc, Script *s,
+ uint32_t slot,
+ const void *params,
+ size_t paramLength);
+ int (*invokeRoot)(const Context *rsc, Script *s);
+ void (*invokeForEach)(const Context *rsc,
+ Script *s,
+ const Allocation * ain,
+ Allocation * aout,
+ const void * usr,
+ uint32_t usrLen,
+ const RsScriptCall *sc);
+ void (*invokeInit)(const Context *rsc, Script *s);
+
+ void (*setGlobalVar)(const Context *rsc, const Script *s,
+ uint32_t slot,
+ void *data,
+ size_t dataLength);
+ void (*setGlobalBind)(const Context *rsc, const Script *s,
+ uint32_t slot,
+ void *data);
+ void (*setGlobalObj)(const Context *rsc, const Script *s,
+ uint32_t slot,
+ ObjectBase *data);
+
+ void (*destroy)(const Context *rsc, Script *s);
+ } script;
+
+ struct {
+ bool (*init)(const Context *rsc, Allocation *alloc, bool forceZero);
+ void (*destroy)(const Context *rsc, Allocation *alloc);
+
+ void (*resize)(const Context *rsc, const Allocation *alloc, const Type *newType,
+ bool zeroNew);
+ void (*syncAll)(const Context *rsc, const Allocation *alloc, RsAllocationUsageType src);
+ void (*markDirty)(const Context *rsc, const Allocation *alloc);
+
+ void (*data1D)(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t lod, uint32_t count,
+ const void *data, uint32_t sizeBytes);
+ void (*data2D)(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);
+ void (*data3D)(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 (*elementData1D)(const Context *rsc, const Allocation *alloc, uint32_t x,
+ const void *data, uint32_t elementOff, uint32_t sizeBytes);
+ void (*elementData2D)(const Context *rsc, const Allocation *alloc, uint32_t x, uint32_t y,
+ const void *data, uint32_t elementOff, uint32_t sizeBytes);
+
+
+ } allocation;
+
+ struct {
+ bool (*init)(const Context *rsc, const ProgramStore *ps);
+ void (*setActive)(const Context *rsc, const ProgramStore *ps);
+ void (*destroy)(const Context *rsc, const ProgramStore *ps);
+ } store;
+
+ struct {
+ bool (*init)(const Context *rsc, const ProgramRaster *ps);
+ void (*setActive)(const Context *rsc, const ProgramRaster *ps);
+ void (*destroy)(const Context *rsc, const ProgramRaster *ps);
+ } raster;
+
+ struct {
+ bool (*init)(const Context *rsc, const ProgramVertex *pv,
+ const char* shader, uint32_t shaderLen);
+ void (*setActive)(const Context *rsc, const ProgramVertex *pv);
+ void (*destroy)(const Context *rsc, const ProgramVertex *pv);
+ } vertex;
+
+ struct {
+ bool (*init)(const Context *rsc, const ProgramFragment *pf,
+ const char* shader, uint32_t shaderLen);
+ void (*setActive)(const Context *rsc, const ProgramFragment *pf);
+ void (*destroy)(const Context *rsc, const ProgramFragment *pf);
+ } fragment;
+
+ struct {
+ bool (*init)(const Context *rsc, const Mesh *m);
+ void (*draw)(const Context *rsc, const Mesh *m, uint32_t primIndex, uint32_t start, uint32_t len);
+ void (*destroy)(const Context *rsc, const Mesh *m);
+ } mesh;
+
+ struct {
+ bool (*init)(const Context *rsc, const Sampler *m);
+ void (*destroy)(const Context *rsc, const Sampler *m);
+ } sampler;
+
+ struct {
+ bool (*init)(const Context *rsc, const FBOCache *fb);
+ void (*setActive)(const Context *rsc, const FBOCache *fb);
+ void (*destroy)(const Context *rsc, const FBOCache *fb);
+ } framebuffer;
+
+} RsdHalFunctions;
+
+
+}
+}
+
+
+bool rsdHalInit(android::renderscript::Context *, uint32_t version_major, uint32_t version_minor);
+
+#endif
+
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 4ac5b7f..b3f6c55 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -4,7 +4,7 @@
void printFileHeader(FILE *f) {
fprintf(f, "/*\n");
- fprintf(f, " * Copyright (C) 2010 The Android Open Source Project\n");
+ fprintf(f, " * Copyright (C) 2011 The Android Open Source Project\n");
fprintf(f, " *\n");
fprintf(f, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
fprintf(f, " * you may not use this file except in compliance with the License.\n");
@@ -53,6 +53,10 @@ void printVarType(FILE *f, const VarType *vt) {
fprintf(f, "*");
}
}
+}
+
+void printVarTypeAndName(FILE *f, const VarType *vt) {
+ printVarType(f, vt);
if (vt->name[0]) {
fprintf(f, " %s", vt->name);
@@ -65,7 +69,7 @@ void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) {
if (ct || assumePrevious) {
fprintf(f, ", ");
}
- printVarType(f, &api->params[ct]);
+ printVarTypeAndName(f, &api->params[ct]);
}
}
@@ -86,41 +90,96 @@ void printStructures(FILE *f) {
for (ct2=0; ct2 < api->paramCount; ct2++) {
fprintf(f, " ");
- printVarType(f, &api->params[ct2]);
+ printVarTypeAndName(f, &api->params[ct2]);
fprintf(f, ";\n");
}
fprintf(f, "};\n\n");
}
}
-void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext) {
- printVarType(f, &api->ret);
- fprintf(f, " %s%s (", prefix, api->name);
- if (addContext) {
- fprintf(f, "Context *");
+void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext, int isFnPtr) {
+ printVarTypeAndName(f, &api->ret);
+ if (isFnPtr) {
+ char t[1024];
+ strcpy(t, api->name);
+ if (strlen(prefix) == 0) {
+ if (t[0] > 'A' && t[0] < 'Z') {
+ t[0] -= 'A' - 'a';
+ }
+ }
+ fprintf(f, " (* %s%s) (", prefix, api->name);
} else {
- fprintf(f, "RsContext rsc");
+ fprintf(f, " %s%s (", prefix, api->name);
}
- printArgList(f, api, 1);
+ if (!api->nocontext) {
+ if (addContext) {
+ fprintf(f, "Context *");
+ } else {
+ fprintf(f, "RsContext rsc");
+ }
+ }
+ printArgList(f, api, !api->nocontext);
fprintf(f, ")");
}
void printFuncDecls(FILE *f, const char *prefix, int addContext) {
int ct;
for (ct=0; ct < apiCount; ct++) {
- printFuncDecl(f, &apis[ct], prefix, addContext);
+ printFuncDecl(f, &apis[ct], prefix, addContext, 0);
fprintf(f, ";\n");
}
fprintf(f, "\n\n");
}
+void printFuncPointers(FILE *f, int addContext) {
+ fprintf(f, "\n");
+ fprintf(f, "typedef struct RsApiEntrypoints {\n");
+ int ct;
+ for (ct=0; ct < apiCount; ct++) {
+ fprintf(f, " ");
+ printFuncDecl(f, &apis[ct], "", addContext, 1);
+ fprintf(f, ";\n");
+ }
+ fprintf(f, "} RsApiEntrypoints_t;\n\n");
+}
+
void printPlaybackFuncs(FILE *f, const char *prefix) {
int ct;
for (ct=0; ct < apiCount; ct++) {
+ if (apis[ct].direct) {
+ continue;
+ }
+
fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
}
}
+static int hasInlineDataPointers(const ApiEntry * api) {
+ int ret = 0;
+ int ct;
+ if (api->sync || api->ret.typeName[0]) {
+ return 0;
+ }
+ for (ct=0; ct < api->paramCount; ct++) {
+ const VarType *vt = &api->params[ct];
+
+ if (!vt->isConst && vt->ptrLevel) {
+ // Non-const pointers cannot be inlined.
+ return 0;
+ }
+ if (vt->ptrLevel > 1) {
+ // not handled yet.
+ return 0;
+ }
+
+ if (vt->isConst && vt->ptrLevel) {
+ // Non-const pointers cannot be inlined.
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
void printApiCpp(FILE *f) {
int ct;
int ct2;
@@ -130,54 +189,233 @@ void printApiCpp(FILE *f) {
fprintf(f, "#include \"rsThreadIO.h\"\n");
//fprintf(f, "#include \"rsgApiStructs.h\"\n");
fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
+ fprintf(f, "#include \"rsFifo.h\"\n");
fprintf(f, "\n");
fprintf(f, "using namespace android;\n");
fprintf(f, "using namespace android::renderscript;\n");
- fprintf(f, "#include \"rsHandcode.h\"\n");
fprintf(f, "\n");
+ printFuncPointers(f, 0);
+
+ // Generate RS funcs for local fifo
for (ct=0; ct < apiCount; ct++) {
int needFlush = 0;
const ApiEntry * api = &apis[ct];
- printFuncDecl(f, api, "rs", 0);
+ fprintf(f, "static ");
+ printFuncDecl(f, api, "LF_", 0, 0);
fprintf(f, "\n{\n");
- if (api->handcodeApi) {
- fprintf(f, " rsHCAPI_%s(rsc", api->name);
+ if (api->direct) {
+ fprintf(f, " ");
+ if (api->ret.typeName[0]) {
+ fprintf(f, "return ");
+ }
+ fprintf(f, "rsi_%s(", api->name);
+ if (!api->nocontext) {
+ fprintf(f, "(Context *)rsc");
+ }
for (ct2=0; ct2 < api->paramCount; ct2++) {
const VarType *vt = &api->params[ct2];
- fprintf(f, ", %s", vt->name);
+ if (ct2 > 0 || !api->nocontext) {
+ fprintf(f, ", ");
+ }
+ fprintf(f, "%s", vt->name);
}
fprintf(f, ");\n");
} else {
fprintf(f, " ThreadIO *io = &((Context *)rsc)->mIO;\n");
+ fprintf(f, " const uint32_t size = sizeof(RS_CMD_%s);\n", api->name);
+ if (hasInlineDataPointers(api)) {
+ fprintf(f, " uint32_t dataSize = 0;\n");
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ if (vt->isConst && vt->ptrLevel) {
+ fprintf(f, " dataSize += %s_length;\n", vt->name);
+ }
+ }
+ }
+
//fprintf(f, " LOGE(\"add command %s\\n\");\n", api->name);
- fprintf(f, " RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->mToCore.reserve(sizeof(RS_CMD_%s)));\n", api->name, api->name, api->name);
- fprintf(f, " uint32_t size = sizeof(RS_CMD_%s);\n", api->name);
+ if (hasInlineDataPointers(api)) {
+ fprintf(f, " RS_CMD_%s *cmd = NULL;\n", api->name);
+ fprintf(f, " if (dataSize < 1024) {;\n");
+ fprintf(f, " cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, dataSize + size));\n", api->name, api->name);
+ fprintf(f, " } else {\n");
+ fprintf(f, " cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name);
+ fprintf(f, " }\n");
+ fprintf(f, " uint8_t *payload = (uint8_t *)&cmd[1];\n");
+ } else {
+ fprintf(f, " RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name, api->name);
+ }
for (ct2=0; ct2 < api->paramCount; ct2++) {
const VarType *vt = &api->params[ct2];
needFlush += vt->ptrLevel;
- fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name);
+ if (vt->ptrLevel && hasInlineDataPointers(api)) {
+ fprintf(f, " if (dataSize < 1024) {\n");
+ fprintf(f, " memcpy(payload, %s, %s_length);\n", vt->name, vt->name);
+ fprintf(f, " cmd->%s = (", vt->name);
+ printVarType(f, vt);
+ fprintf(f, ")payload;\n");
+ fprintf(f, " payload += %s_length;\n", vt->name);
+ fprintf(f, " } else {\n");
+ fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name);
+ fprintf(f, " }\n");
+
+ } else {
+ fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name);
+ }
}
- if (api->ret.typeName[0]) {
+ if (api->ret.typeName[0] || api->sync) {
needFlush = 1;
}
- fprintf(f, " io->mToCore.commit");
- if (needFlush) {
- fprintf(f, "Sync");
+ if (hasInlineDataPointers(api)) {
+ fprintf(f, " if (dataSize < 1024) {\n");
+ fprintf(f, " io->coreCommit();\n");
+ fprintf(f, " } else {\n");
+ fprintf(f, " io->coreCommitSync();\n");
+ fprintf(f, " }\n");
+ } else {
+ fprintf(f, " io->coreCommit");
+ if (needFlush) {
+ fprintf(f, "Sync");
+ }
+ fprintf(f, "();\n");
}
- fprintf(f, "(RS_CMD_ID_%s, size);\n", api->name);
if (api->ret.typeName[0]) {
- fprintf(f, " return reinterpret_cast<");
+ fprintf(f, "\n ");
printVarType(f, &api->ret);
- fprintf(f, ">(io->mToCoreRet);\n");
+ fprintf(f, " ret;\n");
+ fprintf(f, " io->coreGetReturn(&ret, sizeof(ret));\n");
+ fprintf(f, " return ret;\n");
}
}
fprintf(f, "};\n\n");
+
+
+ fprintf(f, "static ");
+ printFuncDecl(f, api, "RF_", 0, 0);
+ fprintf(f, "\n{\n");
+ fprintf(f, " Fifo *f = NULL;\n");
+ fprintf(f, " RS_CMD_%s cmd;\n", api->name);
+ fprintf(f, " const uint32_t cmdSize = sizeof(cmd);\n");
+ fprintf(f, " const uint32_t cmdID = RS_CMD_ID_%s;\n", api->name);
+ fprintf(f, " f->writeAsync(&cmdID, sizeof(cmdID));\n");
+ fprintf(f, " intptr_t offset = cmdSize;\n");
+ fprintf(f, " uint32_t dataSize = 0;\n");
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ if (vt->isConst && vt->ptrLevel) {
+ switch(vt->ptrLevel) {
+ case 1:
+ fprintf(f, " dataSize += %s_length;\n", vt->name);
+ break;
+ case 2:
+ fprintf(f, " for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+ fprintf(f, " dataSize += %s_length[ct];\n", vt->name);
+ fprintf(f, " }\n");
+ break;
+ default:
+ printf("pointer level not handled!!");
+ }
+ }
+ }
+ fprintf(f, "\n");
+
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ switch(vt->ptrLevel) {
+ case 0:
+ fprintf(f, " cmd.%s = %s;\n", vt->name, vt->name);
+ break;
+ case 1:
+ fprintf(f, " cmd.%s = (", vt->name);
+ printVarType(f, vt);
+ fprintf(f, ")offset;\n");
+ fprintf(f, " offset += %s_length;\n", vt->name);
+ break;
+ case 2:
+ fprintf(f, " cmd.%s = (", vt->name);
+ printVarType(f, vt);
+ fprintf(f, ")offset;\n");
+ fprintf(f, " for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+ fprintf(f, " offset += %s_length[ct];\n", vt->name);
+ fprintf(f, " }\n");
+ break;
+ default:
+ fprintf(stderr, "pointer level not handled!!");
+ }
+ }
+ fprintf(f, "\n");
+
+ fprintf(f, " f->writeAsync(&cmd, cmdSize);\n");
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ if (vt->ptrLevel == 1) {
+ fprintf(f, " f->writeAsync(%s, %s_length);\n", vt->name, vt->name);
+ }
+ if (vt->ptrLevel == 2) {
+ fprintf(f, " for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+ fprintf(f, " f->writeAsync(%s, %s_length[ct]);\n", vt->name, vt->name);
+ fprintf(f, " offset += %s_length[ct];\n", vt->name);
+ fprintf(f, " }\n");
+ }
+ }
+
+ if (api->ret.typeName[0]) {
+ fprintf(f, " ");
+ printVarType(f, &api->ret);
+ fprintf(f, " retValue;\n");
+ fprintf(f, " f->writeWaitReturn(&retValue, sizeof(retValue));\n");
+ fprintf(f, " return retValue;\n");
+ }
+ fprintf(f, "}\n\n");
+ }
+
+ fprintf(f, "\n");
+ fprintf(f, "static RsApiEntrypoints_t s_LocalTable = {\n");
+ for (ct=0; ct < apiCount; ct++) {
+ fprintf(f, " LF_%s,\n", apis[ct].name);
+ }
+ fprintf(f, "};\n");
+
+ fprintf(f, "\n");
+ fprintf(f, "static RsApiEntrypoints_t s_RemoteTable = {\n");
+ for (ct=0; ct < apiCount; ct++) {
+ fprintf(f, " RF_%s,\n", apis[ct].name);
+ }
+ fprintf(f, "};\n");
+
+ fprintf(f, "static RsApiEntrypoints_t *s_CurrentTable = &s_LocalTable;\n\n");
+ for (ct=0; ct < apiCount; ct++) {
+ int needFlush = 0;
+ const ApiEntry * api = &apis[ct];
+
+ printFuncDecl(f, api, "rs", 0, 0);
+ fprintf(f, "\n{\n");
+ fprintf(f, " ");
+ if (api->ret.typeName[0]) {
+ fprintf(f, "return ");
+ }
+ fprintf(f, "s_CurrentTable->%s(", api->name);
+
+ if (!api->nocontext) {
+ fprintf(f, "(Context *)rsc");
+ }
+
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ if (ct2 > 0 || !api->nocontext) {
+ fprintf(f, ", ");
+ }
+ fprintf(f, "%s", vt->name);
+ }
+ fprintf(f, ");\n");
+ fprintf(f, "}\n\n");
}
+
}
void printPlaybackCpp(FILE *f) {
@@ -192,37 +430,111 @@ void printPlaybackCpp(FILE *f) {
fprintf(f, "\n");
fprintf(f, "namespace android {\n");
fprintf(f, "namespace renderscript {\n");
- fprintf(f, "#include \"rsHandcode.h\"\n");
fprintf(f, "\n");
for (ct=0; ct < apiCount; ct++) {
const ApiEntry * api = &apis[ct];
- fprintf(f, "void rsp_%s(Context *con, const void *vp)\n", api->name);
- fprintf(f, "{\n");
- if (api->handcodePlay) {
- fprintf(f, " rsHCPLAY_%s(con, vp);\n", api->name);
- } else {
- //fprintf(f, " LOGE(\"play command %s\\n\");\n", api->name);
- fprintf(f, " const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
- fprintf(f, " ");
- if (api->ret.typeName[0]) {
- fprintf(f, "con->mIO.mToCoreRet = (intptr_t)");
+ if (api->direct) {
+ continue;
+ }
+
+ fprintf(f, "void rsp_%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
+
+ //fprintf(f, " LOGE(\"play command %s\\n\");\n", api->name);
+ fprintf(f, " const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
+
+ fprintf(f, " ");
+ if (api->ret.typeName[0]) {
+ fprintf(f, "\n ");
+ printVarType(f, &api->ret);
+ fprintf(f, " ret = ");
+ }
+ fprintf(f, "rsi_%s(con", api->name);
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ fprintf(f, ",\n cmd->%s", vt->name);
+ }
+ fprintf(f, ");\n");
+
+ if (api->ret.typeName[0]) {
+ fprintf(f, " con->mIO.coreSetReturn(&ret, sizeof(ret));\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ for (ct=0; ct < apiCount; ct++) {
+ const ApiEntry * api = &apis[ct];
+
+ fprintf(f, "void rspr_%s(Context *con, Fifo *f, uint8_t *scratch, size_t scratchSize) {\n", api->name);
+
+ //fprintf(f, " LOGE(\"play command %s\\n\");\n", api->name);
+ fprintf(f, " RS_CMD_%s cmd;\n", api->name);
+ fprintf(f, " f->read(&cmd, sizeof(cmd));\n");
+
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ if (vt->ptrLevel == 1) {
+ fprintf(f, " cmd.%s = (", vt->name);
+ printVarType(f, vt);
+ fprintf(f, ")scratch;\n");
+ fprintf(f, " f->read(scratch, cmd.%s_length);\n", vt->name);
+ fprintf(f, " scratch += cmd.%s_length;\n", vt->name);
}
- fprintf(f, "rsi_%s(con", api->name);
- for (ct2=0; ct2 < api->paramCount; ct2++) {
- const VarType *vt = &api->params[ct2];
- fprintf(f, ",\n cmd->%s", vt->name);
+ if (vt->ptrLevel == 2) {
+ fprintf(f, " size_t sum_%s = 0;\n", vt->name);
+ fprintf(f, " for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
+ fprintf(f, " ((size_t *)scratch)[ct] = cmd.%s_length[ct];\n", vt->name);
+ fprintf(f, " sum_%s += cmd.%s_length[ct];\n", vt->name, vt->name);
+ fprintf(f, " }\n");
+ fprintf(f, " f->read(scratch, sum_%s);\n", vt->name);
+ fprintf(f, " scratch += sum_%s;\n", vt->name);
}
- fprintf(f, ");\n");
}
+ fprintf(f, "\n");
+
+ if (api->ret.typeName[0]) {
+ fprintf(f, " ");
+ printVarType(f, &api->ret);
+ fprintf(f, " ret =\n");
+ }
+
+ fprintf(f, " rsi_%s(", api->name);
+ if (!api->nocontext) {
+ fprintf(f, "con");
+ }
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ if (ct2 > 0 || !api->nocontext) {
+ fprintf(f, ",\n");
+ }
+ fprintf(f, " cmd.%s", vt->name);
+ }
+ fprintf(f, ");\n");
+
+ if (api->ret.typeName[0]) {
+ fprintf(f, " f->readReturn(&ret, sizeof(ret));\n");
+ }
+
fprintf(f, "};\n\n");
}
- fprintf(f, "RsPlaybackFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
+ fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
fprintf(f, " NULL,\n");
for (ct=0; ct < apiCount; ct++) {
- fprintf(f, " %s%s,\n", "rsp_", apis[ct].name);
+ if (apis[ct].direct) {
+ fprintf(f, " NULL,\n");
+ } else {
+ fprintf(f, " %s%s,\n", "rsp_", apis[ct].name);
+ }
+ }
+ fprintf(f, "};\n");
+
+ fprintf(f, "RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i] = {\n", apiCount + 1);
+ fprintf(f, " NULL,\n");
+ for (ct=0; ct < apiCount; ct++) {
+ fprintf(f, " %s%s,\n", "rspr_", apis[ct].name);
}
fprintf(f, "};\n");
@@ -230,6 +542,8 @@ void printPlaybackCpp(FILE *f) {
fprintf(f, "};\n");
}
+void yylex();
+
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
@@ -258,14 +572,21 @@ int main(int argc, char **argv) {
{
fprintf(f, "\n");
fprintf(f, "#include \"rsContext.h\"\n");
+ fprintf(f, "#include \"rsFifo.h\"\n");
fprintf(f, "\n");
fprintf(f, "namespace android {\n");
fprintf(f, "namespace renderscript {\n");
printStructures(f);
printFuncDecls(f, "rsi_", 1);
printPlaybackFuncs(f, "rsp_");
- fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *);\n");
- fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[%i];\n", apiCount + 1);
+ fprintf(f, "\n\ntypedef struct RsPlaybackRemoteHeaderRec {\n");
+ fprintf(f, " uint32_t command;\n");
+ fprintf(f, " uint32_t size;\n");
+ fprintf(f, "} RsPlaybackRemoteHeader;\n\n");
+ fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
+ fprintf(f, "typedef void (*RsPlaybackRemoteFunc)(Context *, Fifo *, uint8_t *scratch, size_t scratchSize);\n");
+ fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
+ fprintf(f, "extern RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i];\n", apiCount + 1);
fprintf(f, "}\n");
fprintf(f, "}\n");
@@ -290,6 +611,19 @@ int main(int argc, char **argv) {
printPlaybackCpp(f);
}
break;
+
+ case '4': // rsgApiStream.cpp
+ {
+ printFileHeader(f);
+ printPlaybackCpp(f);
+ }
+
+ case '5': // rsgApiStreamReplay.cpp
+ {
+ printFileHeader(f);
+ printPlaybackCpp(f);
+ }
+ break;
}
fclose(f);
return 0;
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index 67ffc3d..d53bc95 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -1,6 +1,46 @@
#ifndef __RS_GRAPHICS_RSH__
#define __RS_GRAPHICS_RSH__
+/**
+ * Set the color target used for all subsequent rendering calls
+ * @param colorTarget
+ * @param slot
+ */
+extern void __attribute__((overloadable))
+ rsgBindColorTarget(rs_allocation colorTarget, uint slot);
+
+/**
+ * Clear the previously set color target
+ * @param slot
+ */
+extern void __attribute__((overloadable))
+ rsgClearColorTarget(uint slot);
+
+/**
+ * Set the depth target used for all subsequent rendering calls
+ * @param depthTarget
+ */
+extern void __attribute__((overloadable))
+ rsgBindDepthTarget(rs_allocation depthTarget);
+
+/**
+ * Clear the previously set depth target
+ */
+extern void __attribute__((overloadable))
+ rsgClearDepthTarget(void);
+
+/**
+ * Clear all color and depth targets and resume rendering into
+ * the framebuffer
+ */
+extern void __attribute__((overloadable))
+ rsgClearAllRenderTargets(void);
+
+/**
+ * Force RenderScript to finish all rendering commands
+ */
+extern uint __attribute__((overloadable))
+ rsgFinish(void);
/**
* Bind a new ProgramFragment to the rendering context.
diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh
index a010096..d9f4b4b 100644
--- a/libs/rs/scriptc/rs_types.rsh
+++ b/libs/rs/scriptc/rs_types.rsh
@@ -36,6 +36,10 @@ typedef float float2 __attribute__((ext_vector_type(2)));
typedef float float3 __attribute__((ext_vector_type(3)));
typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef double double3 __attribute__((ext_vector_type(3)));
+typedef double double4 __attribute__((ext_vector_type(4)));
+
typedef uchar uchar2 __attribute__((ext_vector_type(2)));
typedef uchar uchar3 __attribute__((ext_vector_type(3)));
typedef uchar uchar4 __attribute__((ext_vector_type(4)));
@@ -48,6 +52,10 @@ typedef uint uint2 __attribute__((ext_vector_type(2)));
typedef uint uint3 __attribute__((ext_vector_type(3)));
typedef uint uint4 __attribute__((ext_vector_type(4)));
+typedef ulong ulong2 __attribute__((ext_vector_type(2)));
+typedef ulong ulong3 __attribute__((ext_vector_type(3)));
+typedef ulong ulong4 __attribute__((ext_vector_type(4)));
+
typedef char char2 __attribute__((ext_vector_type(2)));
typedef char char3 __attribute__((ext_vector_type(3)));
typedef char char4 __attribute__((ext_vector_type(4)));
@@ -60,6 +68,9 @@ typedef int int2 __attribute__((ext_vector_type(2)));
typedef int int3 __attribute__((ext_vector_type(3)));
typedef int int4 __attribute__((ext_vector_type(4)));
+typedef long long2 __attribute__((ext_vector_type(2)));
+typedef long long3 __attribute__((ext_vector_type(3)));
+typedef long long4 __attribute__((ext_vector_type(4)));
typedef struct {
float m[16];
diff --git a/libs/rs/spec.h b/libs/rs/spec.h
index 82650a7..ecc5cc7 100644
--- a/libs/rs/spec.h
+++ b/libs/rs/spec.h
@@ -25,7 +25,8 @@ typedef struct {
char name[256];
int sync;
int handcodeApi;
- int handcodePlay;
+ int direct;
+ int nocontext;
int paramCount;
VarType ret;
VarType params[16];
diff --git a/libs/rs/spec.l b/libs/rs/spec.l
index 6a9010fe..a24bfd3 100644
--- a/libs/rs/spec.l
+++ b/libs/rs/spec.l
@@ -20,6 +20,30 @@ ID [a-zA-Z_][a-zA-Z0-9_]*
int typeNextState;
+ void checkPointerType() {
+ VarType *baseType = currType;
+ int curPtrLevel = 0;
+ while (curPtrLevel < baseType->ptrLevel) {
+ currType = &apis[apiCount].params[apis[apiCount].paramCount];
+ currType->type = 4;
+ currType->ptrLevel = curPtrLevel;
+ if (currType->ptrLevel > 0) {
+ currType->isConst = 1;
+ }
+ sprintf(currType->typeName, "%s", "size_t");
+ switch(baseType->ptrLevel - curPtrLevel) {
+ case 1:
+ sprintf(currType->name, "%s_length", baseType->name);
+ break;
+ case 2:
+ sprintf(currType->name, "%s_length_length", baseType->name);
+ break;
+ }
+ apis[apiCount].paramCount++;
+ curPtrLevel ++;
+ }
+ }
+
extern "C" int yylex();
%%
@@ -31,6 +55,7 @@ ID [a-zA-Z_][a-zA-Z0-9_]*
<comment>"*"+"/" BEGIN(INITIAL);
<*>" " //printf("found ' '\n");
+<*>"\t" //printf("found ' '\n");
<*>"\n" ++num_lines; //printf("found lf \n");
{ID} {
@@ -51,8 +76,12 @@ ID [a-zA-Z_][a-zA-Z0-9_]*
apis[apiCount].handcodeApi = 1;
}
-<api_entry2>"handcodePlay" {
- apis[apiCount].handcodePlay = 1;
+<api_entry2>"direct" {
+ apis[apiCount].direct = 1;
+ }
+
+<api_entry2>"nocontext" {
+ apis[apiCount].nocontext = 1;
}
<api_entry2>"ret" {
@@ -145,6 +174,7 @@ ID [a-zA-Z_][a-zA-Z0-9_]*
<api_entry_param>{ID} {
memcpy(currType->name, yytext, yyleng);
+ checkPointerType();
BEGIN(api_entry2);
}
diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk
index 4a0faf0..267e3edf 100644
--- a/libs/surfaceflinger_client/Android.mk
+++ b/libs/surfaceflinger_client/Android.mk
@@ -1,22 +1,9 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
- ISurfaceComposer.cpp \
- ISurface.cpp \
- ISurfaceComposerClient.cpp \
- IGraphicBufferAlloc.cpp \
- LayerState.cpp \
- SharedBufferStack.cpp \
- Surface.cpp \
- SurfaceComposerClient.cpp
+LOCAL_SRC_FILES:=
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libbinder \
- libhardware \
- libui
+LOCAL_SHARED_LIBRARIES :=
LOCAL_MODULE:= libsurfaceflinger_client
diff --git a/libs/surfaceflinger_client/tests/Android.mk b/libs/surfaceflinger_client/tests/Android.mk
deleted file mode 100644
index 212b8e7..0000000
--- a/libs/surfaceflinger_client/tests/Android.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-ifneq ($(TARGET_SIMULATOR),true)
-
-# Build the unit tests.
-test_src_files := \
- Surface_test.cpp \
-
-shared_libraries := \
- libcutils \
- libutils \
- libbinder \
- libsurfaceflinger_client \
- libstlport \
-
-static_libraries := \
- libgtest \
- libgtest_main \
-
-c_includes := \
- bionic \
- bionic/libstdc++/include \
- external/gtest/include \
- external/stlport/stlport \
-
-module_tags := tests
-
-$(foreach file,$(test_src_files), \
- $(eval include $(CLEAR_VARS)) \
- $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
- $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
- $(eval LOCAL_C_INCLUDES := $(c_includes)) \
- $(eval LOCAL_SRC_FILES := $(file)) \
- $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
- $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
- $(eval include $(BUILD_EXECUTABLE)) \
-)
-
-# Build the manual test programs.
-include $(call all-subdir-makefiles)
-
-endif
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk b/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk
deleted file mode 100644
index d3dfe04..0000000
--- a/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- SharedBufferStackTest.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libui \
- libsurfaceflinger_client
-
-LOCAL_MODULE:= test-sharedbufferstack
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_EXECUTABLE)
diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
deleted file mode 100644
index 7ef5926..0000000
--- a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#undef NDEBUG
-
-#include <assert.h>
-#include <cutils/memory.h>
-#include <cutils/log.h>
-#include <utils/Errors.h>
-#include <private/surfaceflinger/SharedBufferStack.h>
-
-using namespace android;
-
-void log(const char* prefix, int *b, size_t num);
-void test0(SharedBufferServer& s, SharedBufferClient& c, size_t num, int* list);
-
-// ----------------------------------------------------------------------------
-
-int main(int argc, char** argv)
-{
- SharedClient client;
- sp<SharedBufferServer> ps(new SharedBufferServer(&client, 0, 4, 0));
- SharedBufferServer& s(*ps);
- SharedBufferClient c(&client, 0, 4, 0);
-
- printf("basic test 0\n");
- int list0[4] = {0, 1, 2, 3};
- test0(s, c, 4, list0);
-
- printf("basic test 1\n");
- int list1[4] = {2, 1, 0, 3};
- test0(s, c, 4, list1);
-
- int b = c.dequeue();
- c.lock(b);
- c.queue(b);
- s.retireAndLock();
-
- printf("basic test 2\n");
- int list2[4] = {1, 2, 3, 0};
- test0(s, c, 4, list2);
-
-
- printf("resize test\n");
- class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback {
- SharedBufferServer& s;
- virtual status_t operator()(int bufferCount) const {
- return s.resize(bufferCount);
- }
- public:
- SetBufferCountIPC(SharedBufferServer& s) : s(s) { }
- } resize(s);
-
- c.setBufferCount(6, resize);
- int list3[6] = {3, 2, 1, 4, 5, 0};
- test0(s, c, 6, list3);
-
- c.setBufferCount(4, resize);
- int list4[4] = {1, 2, 3, 0};
- test0(s, c, 4, list4);
-
- return 0;
-}
-
-void log(const char* prefix, int *b, size_t num)
-{
- printf("%s: ", prefix);
- for (size_t i=0 ; i<num ; i++) {
- printf("%d ", b[i]);
- }
- printf("\n");
-}
-
-// ----------------------------------------------------------------------------
-
-void test0(
- SharedBufferServer& s,
- SharedBufferClient& c,
- size_t num,
- int* list)
-{
- status_t err;
- int b[num], u[num], r[num];
-
- for (size_t i=0 ; i<num ; i++) {
- b[i] = c.dequeue();
- assert(b[i]==list[i]);
- }
- log("DQ", b, num);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- err = c.lock(b[i]);
- assert(err==0);
- }
- log("LK", b, num-1);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- err = c.queue(b[i]);
- assert(err==0);
- }
- log(" Q", b, num-1);
-
-
- for (size_t i=0 ; i<num-1 ; i++) {
- r[i] = s.retireAndLock();
- assert(r[i]==list[i]);
- err = s.unlock(r[i]);
- assert(err == 0);
- }
- log("RT", r, num-1);
-
- err = c.lock(b[num-1]);
- assert(err == 0);
- log("LK", b+num-1, 1);
-
- err = c.queue(b[num-1]);
- assert(err == 0);
- log(" Q", b+num-1, 1);
-
- r[num-1] = s.retireAndLock();
- assert(r[num-1]==list[num-1]);
- err = s.unlock(r[num-1]);
- assert(err == 0);
- log("RT", r+num-1, 1);
-
- // ------------------------------------
- printf("\n");
-
- for (size_t i=0 ; i<num ; i++) {
- b[i] = c.dequeue();
- assert(b[i]==list[i]);
- }
- log("DQ", b, num);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- err = c.lock(b[i]);
- assert(err==0);
- }
- log("LK", b, num-1);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- u[i] = b[num-2-i];
- }
- u[num-1] = b[num-1];
-
- for (size_t i=0 ; i<num-1 ; i++) {
- err = c.queue(u[i]);
- assert(err==0);
- }
- log(" Q", u, num-1);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- r[i] = s.retireAndLock();
- assert(r[i]==u[i]);
- err = s.unlock(r[i]);
- assert(err == 0);
- }
- log("RT", r, num-1);
-
- err = c.lock(b[num-1]);
- assert(err == 0);
- log("LK", b+num-1, 1);
-
- err = c.queue(b[num-1]);
- assert(err == 0);
- log(" Q", b+num-1, 1);
-
- r[num-1] = s.retireAndLock();
- assert(r[num-1]==list[num-1]);
- err = s.unlock(r[num-1]);
- assert(err == 0);
- log("RT", r+num-1, 1);
-
- // ------------------------------------
- printf("\n");
-
- for (size_t i=0 ; i<num ; i++) {
- b[i] = c.dequeue();
- assert(b[i]==u[i]);
- }
- log("DQ", b, num);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- err = c.lock(b[i]);
- assert(err==0);
- }
- log("LK", b, num-1);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- err = c.queue(b[i]);
- assert(err==0);
- }
- log(" Q", b, num-1);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- r[i] = s.retireAndLock();
- assert(r[i]==u[i]);
- err = s.unlock(r[i]);
- assert(err == 0);
- }
- log("RT", r, num-1);
-
- err = c.lock(u[num-1]);
- assert(err == 0);
- log("LK", u+num-1, 1);
-
- err = c.queue(u[num-1]);
- assert(err == 0);
- log(" Q", u+num-1, 1);
-
- r[num-1] = s.retireAndLock();
- assert(r[num-1]==u[num-1]);
- err = s.unlock(r[num-1]);
- assert(err == 0);
- log("RT", r+num-1, 1);
-
- // ------------------------------------
- printf("\n");
-
- b[0] = c.dequeue();
- assert(b[0]==u[0]);
- log("DQ", b, 1);
-
- c.undoDequeue(b[0]);
- assert(err == 0);
- log("UDQ", b, 1);
-
- // ------------------------------------
- printf("\n");
-
- for (size_t i=0 ; i<num ; i++) {
- b[i] = c.dequeue();
- assert(b[i]==u[i]);
- }
- log("DQ", b, num);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- err = c.lock(b[i]);
- assert(err==0);
- }
- log("LK", b, num-1);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- err = c.queue(b[i]);
- assert(err==0);
- }
- log(" Q", b, num-1);
-
- for (size_t i=0 ; i<num-1 ; i++) {
- r[i] = s.retireAndLock();
- assert(r[i]==u[i]);
- err = s.unlock(r[i]);
- assert(err == 0);
- }
- log("RT", r, num-1);
-
- err = c.lock(u[num-1]);
- assert(err == 0);
- log("LK", u+num-1, 1);
-
- err = c.queue(u[num-1]);
- assert(err == 0);
- log(" Q", u+num-1, 1);
-
- r[num-1] = s.retireAndLock();
- assert(r[num-1]==u[num-1]);
- err = s.unlock(r[num-1]);
- assert(err == 0);
- log("RT", r+num-1, 1);
- printf("\n");
-}
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index dc223f9..4393504 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -47,16 +47,16 @@ namespace android {
class NativeBuffer
: public EGLNativeBase<
- android_native_buffer_t,
+ ANativeWindowBuffer,
NativeBuffer,
LightRefBase<NativeBuffer> >
{
public:
NativeBuffer(int w, int h, int f, int u) : BASE() {
- android_native_buffer_t::width = w;
- android_native_buffer_t::height = h;
- android_native_buffer_t::format = f;
- android_native_buffer_t::usage = u;
+ ANativeWindowBuffer::width = w;
+ ANativeWindowBuffer::height = h;
+ ANativeWindowBuffer::format = f;
+ ANativeWindowBuffer::usage = u;
}
private:
friend class LightRefBase<NativeBuffer>;
@@ -201,7 +201,7 @@ int FramebufferNativeWindow::getCurrentBufferIndex() const
}
int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
- android_native_buffer_t** buffer)
+ ANativeWindowBuffer** buffer)
{
FramebufferNativeWindow* self = getSelf(window);
Mutex::Autolock _l(self->mutex);
@@ -229,7 +229,7 @@ int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
}
int FramebufferNativeWindow::lockBuffer(ANativeWindow* window,
- android_native_buffer_t* buffer)
+ ANativeWindowBuffer* buffer)
{
FramebufferNativeWindow* self = getSelf(window);
Mutex::Autolock _l(self->mutex);
@@ -249,7 +249,7 @@ int FramebufferNativeWindow::lockBuffer(ANativeWindow* window,
}
int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
- android_native_buffer_t* buffer)
+ ANativeWindowBuffer* buffer)
{
FramebufferNativeWindow* self = getSelf(window);
Mutex::Autolock _l(self->mutex);
@@ -270,10 +270,10 @@ int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
return res;
}
-int FramebufferNativeWindow::query(ANativeWindow* window,
+int FramebufferNativeWindow::query(const ANativeWindow* window,
int what, int* value)
{
- FramebufferNativeWindow* self = getSelf(window);
+ const FramebufferNativeWindow* self = getSelf(window);
Mutex::Autolock _l(self->mutex);
framebuffer_device_t* fb = self->fbDev;
switch (what) {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 97312a6..54a3ffa 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -33,7 +33,7 @@
namespace android {
// ===========================================================================
-// Buffer and implementation of android_native_buffer_t
+// Buffer and implementation of ANativeWindowBuffer
// ===========================================================================
GraphicBuffer::GraphicBuffer()
@@ -77,7 +77,7 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
handle = inHandle;
}
-GraphicBuffer::GraphicBuffer(android_native_buffer_t* buffer, bool keepOwnership)
+GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership)
: BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mIndex(-1), mWrappedBuffer(buffer)
@@ -119,9 +119,9 @@ void GraphicBuffer::dumpAllocationsToSystemLog()
GraphicBufferAllocator::dumpToSystemLog();
}
-android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
+ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
{
- return static_cast<android_native_buffer_t*>(
+ return static_cast<ANativeWindowBuffer*>(
const_cast<GraphicBuffer*>(this));
}
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 1fc46aa..0af7f80 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -378,6 +378,19 @@ void PointerCoords::copyFrom(const PointerCoords& other) {
}
+// --- PointerProperties ---
+
+bool PointerProperties::operator==(const PointerProperties& other) const {
+ return id == other.id
+ && toolType == other.toolType;
+}
+
+void PointerProperties::copyFrom(const PointerProperties& other) {
+ id = other.id;
+ toolType = other.toolType;
+}
+
+
// --- MotionEvent ---
void MotionEvent::initialize(
@@ -387,6 +400,7 @@ void MotionEvent::initialize(
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
+ int32_t buttonState,
float xOffset,
float yOffset,
float xPrecision,
@@ -394,20 +408,21 @@ void MotionEvent::initialize(
nsecs_t downTime,
nsecs_t eventTime,
size_t pointerCount,
- const int32_t* pointerIds,
+ const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
InputEvent::initialize(deviceId, source);
mAction = action;
mFlags = flags;
mEdgeFlags = edgeFlags;
mMetaState = metaState;
+ mButtonState = buttonState;
mXOffset = xOffset;
mYOffset = yOffset;
mXPrecision = xPrecision;
mYPrecision = yPrecision;
mDownTime = downTime;
- mPointerIds.clear();
- mPointerIds.appendArray(pointerIds, pointerCount);
+ mPointerProperties.clear();
+ mPointerProperties.appendArray(pointerProperties, pointerCount);
mSampleEventTimes.clear();
mSamplePointerCoords.clear();
addSample(eventTime, pointerCoords);
@@ -419,12 +434,13 @@ void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
mFlags = other->mFlags;
mEdgeFlags = other->mEdgeFlags;
mMetaState = other->mMetaState;
+ mButtonState = other->mButtonState;
mXOffset = other->mXOffset;
mYOffset = other->mYOffset;
mXPrecision = other->mXPrecision;
mYPrecision = other->mYPrecision;
mDownTime = other->mDownTime;
- mPointerIds = other->mPointerIds;
+ mPointerProperties = other->mPointerProperties;
if (keepHistory) {
mSampleEventTimes = other->mSampleEventTimes;
@@ -489,9 +505,9 @@ float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
}
ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
- size_t pointerCount = mPointerIds.size();
+ size_t pointerCount = mPointerProperties.size();
for (size_t i = 0; i < pointerCount; i++) {
- if (mPointerIds.itemAt(i) == pointerId) {
+ if (mPointerProperties.itemAt(i).id == pointerId) {
return i;
}
}
@@ -588,21 +604,25 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) {
mFlags = parcel->readInt32();
mEdgeFlags = parcel->readInt32();
mMetaState = parcel->readInt32();
+ mButtonState = parcel->readInt32();
mXOffset = parcel->readFloat();
mYOffset = parcel->readFloat();
mXPrecision = parcel->readFloat();
mYPrecision = parcel->readFloat();
mDownTime = parcel->readInt64();
- mPointerIds.clear();
- mPointerIds.setCapacity(pointerCount);
+ mPointerProperties.clear();
+ mPointerProperties.setCapacity(pointerCount);
mSampleEventTimes.clear();
mSampleEventTimes.setCapacity(sampleCount);
mSamplePointerCoords.clear();
mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
for (size_t i = 0; i < pointerCount; i++) {
- mPointerIds.push(parcel->readInt32());
+ mPointerProperties.push();
+ PointerProperties& properties = mPointerProperties.editTop();
+ properties.id = parcel->readInt32();
+ properties.toolType = parcel->readInt32();
}
while (sampleCount-- > 0) {
@@ -619,7 +639,7 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) {
}
status_t MotionEvent::writeToParcel(Parcel* parcel) const {
- size_t pointerCount = mPointerIds.size();
+ size_t pointerCount = mPointerProperties.size();
size_t sampleCount = mSampleEventTimes.size();
parcel->writeInt32(pointerCount);
@@ -631,6 +651,7 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const {
parcel->writeInt32(mFlags);
parcel->writeInt32(mEdgeFlags);
parcel->writeInt32(mMetaState);
+ parcel->writeInt32(mButtonState);
parcel->writeFloat(mXOffset);
parcel->writeFloat(mYOffset);
parcel->writeFloat(mXPrecision);
@@ -638,7 +659,9 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const {
parcel->writeInt64(mDownTime);
for (size_t i = 0; i < pointerCount; i++) {
- parcel->writeInt32(mPointerIds.itemAt(i));
+ const PointerProperties& properties = mPointerProperties.itemAt(i);
+ parcel->writeInt32(properties.id);
+ parcel->writeInt32(properties.toolType);
}
const PointerCoords* pc = mSamplePointerCoords.array();
@@ -732,7 +755,7 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Posi
LOGD(" %d: position (%0.3f, %0.3f), vx=%0.3f, vy=%0.3f, speed=%0.3f",
id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy));
} else {
- assert(vx == 0 && vy == 0);
+ LOG_ASSERT(vx == 0 && vy == 0);
LOGD(" %d: position (%0.3f, %0.3f), velocity not available",
id, positions[index].x, positions[index].y);
}
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index 93d0d1f..ffdfe66 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -366,6 +366,7 @@ status_t InputPublisher::publishMotionEvent(
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
+ int32_t buttonState,
float xOffset,
float yOffset,
float xPrecision,
@@ -373,16 +374,17 @@ status_t InputPublisher::publishMotionEvent(
nsecs_t downTime,
nsecs_t eventTime,
size_t pointerCount,
- const int32_t* pointerIds,
+ const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
#if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
- "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, "
+ "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
+ "xOffset=%f, yOffset=%f, "
"xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
"pointerCount=%d",
mChannel->getName().string(),
- deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
- xPrecision, yPrecision, downTime, eventTime, pointerCount);
+ deviceId, source, action, flags, edgeFlags, metaState, buttonState,
+ xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
#endif
if (pointerCount > MAX_POINTERS || pointerCount < 1) {
@@ -400,6 +402,7 @@ status_t InputPublisher::publishMotionEvent(
mSharedMessage->motion.flags = flags;
mSharedMessage->motion.edgeFlags = edgeFlags;
mSharedMessage->motion.metaState = metaState;
+ mSharedMessage->motion.buttonState = buttonState;
mSharedMessage->motion.xOffset = xOffset;
mSharedMessage->motion.yOffset = yOffset;
mSharedMessage->motion.xPrecision = xPrecision;
@@ -411,7 +414,7 @@ status_t InputPublisher::publishMotionEvent(
mSharedMessage->motion.sampleData[0].eventTime = eventTime;
for (size_t i = 0; i < pointerCount; i++) {
- mSharedMessage->motion.pointerIds[i] = pointerIds[i];
+ mSharedMessage->motion.pointerProperties[i].copyFrom(pointerProperties[i]);
mSharedMessage->motion.sampleData[0].coords[i].copyFrom(pointerCoords[i]);
}
@@ -694,6 +697,7 @@ void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
mSharedMessage->motion.flags,
mSharedMessage->motion.edgeFlags,
mSharedMessage->motion.metaState,
+ mSharedMessage->motion.buttonState,
mSharedMessage->motion.xOffset,
mSharedMessage->motion.yOffset,
mSharedMessage->motion.xPrecision,
@@ -701,7 +705,7 @@ void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
mSharedMessage->motion.downTime,
mSharedMessage->motion.sampleData[0].eventTime,
mSharedMessage->motion.pointerCount,
- mSharedMessage->motion.pointerIds,
+ mSharedMessage->motion.pointerProperties,
mSharedMessage->motion.sampleData[0].coords);
size_t sampleCount = mSharedMessage->motion.sampleCount;
diff --git a/libs/ui/tests/InputEvent_test.cpp b/libs/ui/tests/InputEvent_test.cpp
index b77489e..e48d5b7 100644
--- a/libs/ui/tests/InputEvent_test.cpp
+++ b/libs/ui/tests/InputEvent_test.cpp
@@ -232,7 +232,14 @@ const float MotionEventTest::X_OFFSET = 1.0f;
const float MotionEventTest::Y_OFFSET = 1.1f;
void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
- int32_t pointerIds[] = { 1, 2 };
+ PointerProperties pointerProperties[2];
+ pointerProperties[0].clear();
+ pointerProperties[0].id = 1;
+ pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ pointerProperties[1].clear();
+ pointerProperties[1].id = 2;
+ pointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+
PointerCoords pointerCoords[2];
pointerCoords[0].clear();
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 10);
@@ -256,10 +263,10 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
- AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON,
+ AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
- 2, pointerIds, pointerCoords);
+ 2, pointerProperties, pointerCoords);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
@@ -311,6 +318,7 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
ASSERT_EQ(AMETA_ALT_ON, event->getMetaState());
+ ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState());
ASSERT_EQ(X_OFFSET, event->getXOffset());
ASSERT_EQ(Y_OFFSET, event->getYOffset());
ASSERT_EQ(2.0f, event->getXPrecision());
@@ -319,7 +327,9 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
ASSERT_EQ(2U, event->getPointerCount());
ASSERT_EQ(1, event->getPointerId(0));
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, event->getToolType(0));
ASSERT_EQ(2, event->getPointerId(1));
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, event->getToolType(1));
ASSERT_EQ(2U, event->getHistorySize());
@@ -534,19 +544,20 @@ TEST_F(MotionEventTest, Transform) {
const float ROTATION = ARC * 2;
const size_t pointerCount = 11;
- int pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
for (size_t i = 0; i < pointerCount; i++) {
float angle = float(i * ARC * PI_180);
- pointerIds[i] = i;
+ pointerProperties[i].clear();
+ pointerProperties[i].id = i;
pointerCoords[i].clear();
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, sinf(angle) * RADIUS + 3);
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, -cosf(angle) * RADIUS + 2);
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
}
MotionEvent event;
- event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
float originalRawX = 0 + 3;
float originalRawY = -RADIUS + 2;
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index 6e18a4f..fcc4cad 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -156,13 +156,19 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
+ const int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
const float xOffset = -10;
const float yOffset = -20;
const float xPrecision = 0.25;
const float yPrecision = 0.5;
const nsecs_t downTime = 3;
const size_t pointerCount = 3;
- const int32_t pointerIds[pointerCount] = { 2, 0, 1 };
+ PointerProperties pointerProperties[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerProperties[i].id = (i + 2) % pointerCount;
+ pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
Vector<nsecs_t> sampleEventTimes;
Vector<PointerCoords> samplePointerCoords;
@@ -186,8 +192,9 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
}
status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
- metaState, xOffset, yOffset, xPrecision, yPrecision,
- downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
+ metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
+ downTime, sampleEventTimes[0], pointerCount,
+ pointerProperties, samplePointerCoords.array());
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
@@ -234,6 +241,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
EXPECT_EQ(flags, motionEvent->getFlags());
EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
EXPECT_EQ(metaState, motionEvent->getMetaState());
+ EXPECT_EQ(buttonState, motionEvent->getButtonState());
EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
EXPECT_EQ(downTime, motionEvent->getDownTime());
@@ -243,7 +251,8 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
for (size_t i = 0; i < pointerCount; i++) {
SCOPED_TRACE(i);
- EXPECT_EQ(pointerIds[i], motionEvent->getPointerId(i));
+ EXPECT_EQ(pointerProperties[i].id, motionEvent->getPointerId(i));
+ EXPECT_EQ(pointerProperties[i].toolType, motionEvent->getToolType(i));
}
for (size_t sampleIndex = 0; sampleIndex < lastSampleIndex; sampleIndex++) {
@@ -352,17 +361,20 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsErr
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = 1;
- int32_t pointerIds[pointerCount] = { 0 };
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
- pointerCoords[0].clear();
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerIds, pointerCoords);
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerIds, pointerCoords);
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(INVALID_OPERATION, status)
<< "publisher publishMotionEvent should return INVALID_OPERATION because ";
"the publisher was not reset";
@@ -373,11 +385,11 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessTha
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = 0;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerIds, pointerCoords);
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
@@ -387,11 +399,15 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreater
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = MAX_POINTERS + 1;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerIds, pointerCoords);
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
@@ -432,11 +448,15 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenPublishedMotionEven
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = MAX_POINTERS;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status);
status = mPublisher->appendMotionSample(0, pointerCoords);
@@ -449,11 +469,15 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenAlreadyConsumed_Ret
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = MAX_POINTERS;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status);
status = mPublisher->sendDispatchSignal();
@@ -476,11 +500,15 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenBufferFull_ReturnsE
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = MAX_POINTERS;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status);
for (int count = 1;; count++) {
diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp
index 0b4d1ac..22034c5 100644
--- a/libs/utils/AssetManager.cpp
+++ b/libs/utils/AssetManager.cpp
@@ -36,6 +36,7 @@
#include <dirent.h>
#include <errno.h>
#include <assert.h>
+#include <strings.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -1998,4 +1999,3 @@ int AssetManager::ZipSet::getIndex(const String8& zip) const
return mZipPath.size()-1;
}
-
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index adb3174..f963058 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -20,12 +20,15 @@
#include <utils/ByteOrder.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#include <cutils/log.h>
namespace android {
+static const bool DEBUG = false;
+
/*
* File Format (v1):
*
@@ -75,6 +78,7 @@ BackupDataWriter::write_padding_for(int n)
paddingSize = padding_extra(n);
if (paddingSize > 0) {
uint32_t padding = 0xbcbcbcbc;
+ if (DEBUG) LOGI("writing %d padding bytes for %d", paddingSize, n);
amt = write(m_fd, &padding, paddingSize);
if (amt != paddingSize) {
m_status = errno;
@@ -107,8 +111,8 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
} else {
k = key;
}
- if (false) {
- LOGD("Writing entity: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(), key.string(),
+ if (DEBUG) {
+ LOGD("Writing header: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(), key.string(),
dataSize);
}
@@ -121,6 +125,7 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
header.keyLen = tolel(keyLen);
header.dataSize = tolel(dataSize);
+ if (DEBUG) LOGI("writing entity header, %d bytes", sizeof(entity_header_v1));
amt = write(m_fd, &header, sizeof(entity_header_v1));
if (amt != sizeof(entity_header_v1)) {
m_status = errno;
@@ -128,6 +133,7 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
}
m_pos += amt;
+ if (DEBUG) LOGI("writing entity header key, %d bytes", keyLen+1);
amt = write(m_fd, k.string(), keyLen+1);
if (amt != keyLen+1) {
m_status = errno;
@@ -145,7 +151,12 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
status_t
BackupDataWriter::WriteEntityData(const void* data, size_t size)
{
+ if (DEBUG) LOGD("Writing data: size=%lu", (unsigned long) size);
+
if (m_status != NO_ERROR) {
+ if (DEBUG) {
+ LOGD("Not writing data - stream in error state %d (%s)", m_status, strerror(m_status));
+ }
return m_status;
}
@@ -155,6 +166,7 @@ BackupDataWriter::WriteEntityData(const void* data, size_t size)
ssize_t amt = write(m_fd, data, size);
if (amt != (ssize_t)size) {
m_status = errno;
+ if (DEBUG) LOGD("write returned error %d (%s)", m_status, strerror(m_status));
return m_status;
}
m_pos += amt;
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
index 4ad9b51..87549fe 100644
--- a/libs/utils/BackupHelpers.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -442,6 +442,278 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
return 0;
}
+// Utility function, equivalent to stpcpy(): perform a strcpy, but instead of
+// returning the initial dest, return a pointer to the trailing NUL.
+static char* strcpy_ptr(char* dest, const char* str) {
+ if (dest && str) {
+ while ((*dest = *str) != 0) {
+ dest++;
+ str++;
+ }
+ }
+ return dest;
+}
+
+static void calc_tar_checksum(char* buf) {
+ // [ 148 : 8 ] checksum -- to be calculated with this field as space chars
+ memset(buf + 148, ' ', 8);
+
+ uint16_t sum = 0;
+ for (uint8_t* p = (uint8_t*) buf; p < ((uint8_t*)buf) + 512; p++) {
+ sum += *p;
+ }
+
+ // Now write the real checksum value:
+ // [ 148 : 8 ] checksum: 6 octal digits [leading zeroes], NUL, SPC
+ sprintf(buf + 148, "%06o", sum); // the trailing space is already in place
+}
+
+// Returns number of bytes written
+static int write_pax_header_entry(char* buf, const char* key, const char* value) {
+ // start with the size of "1 key=value\n"
+ int len = strlen(key) + strlen(value) + 4;
+ if (len > 9) len++;
+ if (len > 99) len++;
+ if (len > 999) len++;
+ // since PATH_MAX is 4096 we don't expect to have to generate any single
+ // header entry longer than 9999 characters
+
+ return sprintf(buf, "%d %s=%s\n", len, key, value);
+}
+
+int write_tarfile(const String8& packageName, const String8& domain,
+ const String8& rootpath, const String8& filepath, BackupDataWriter* writer)
+{
+ // In the output stream everything is stored relative to the root
+ const char* relstart = filepath.string() + rootpath.length();
+ if (*relstart == '/') relstart++; // won't be true when path == rootpath
+ String8 relpath(relstart);
+
+ // If relpath is empty, it means this is the top of one of the standard named
+ // domain directories, so we should just skip it
+ if (relpath.length() == 0) {
+ return 0;
+ }
+
+ // Too long a name for the ustar format?
+ // "apps/" + packagename + '/' + domainpath < 155 chars
+ // relpath < 100 chars
+ bool needExtended = false;
+ if ((5 + packageName.length() + 1 + domain.length() >= 155) || (relpath.length() >= 100)) {
+ needExtended = true;
+ }
+
+ // Non-7bit-clean path also means needing pax extended format
+ if (!needExtended) {
+ for (size_t i = 0; i < filepath.length(); i++) {
+ if ((filepath[i] & 0x80) != 0) {
+ needExtended = true;
+ break;
+ }
+ }
+ }
+
+ int err = 0;
+ struct stat64 s;
+ if (lstat64(filepath.string(), &s) != 0) {
+ err = errno;
+ LOGE("Error %d (%s) from lstat64(%s)", err, strerror(err), filepath.string());
+ return err;
+ }
+
+ String8 fullname; // for pax later on
+ String8 prefix;
+
+ const int isdir = S_ISDIR(s.st_mode);
+ if (isdir) s.st_size = 0; // directories get no actual data in the tar stream
+
+ // !!! TODO: use mmap when possible to avoid churning the buffer cache
+ // !!! TODO: this will break with symlinks; need to use readlink(2)
+ int fd = open(filepath.string(), O_RDONLY);
+ if (fd < 0) {
+ err = errno;
+ LOGE("Error %d (%s) from open(%s)", err, strerror(err), filepath.string());
+ return err;
+ }
+
+ // read/write up to this much at a time.
+ const size_t BUFSIZE = 32 * 1024;
+ char* buf = new char[BUFSIZE];
+ char* paxHeader = buf + 512; // use a different chunk of it as separate scratch
+ char* paxData = buf + 1024;
+
+ if (buf == NULL) {
+ LOGE("Out of mem allocating transfer buffer");
+ err = ENOMEM;
+ goto cleanup;
+ }
+
+ // Good to go -- first construct the standard tar header at the start of the buffer
+ memset(buf, 0, BUFSIZE);
+
+ // Magic fields for the ustar file format
+ strcat(buf + 257, "ustar");
+ strcat(buf + 263, "00");
+
+ // [ 265 : 32 ] user name, ignored on restore
+ // [ 297 : 32 ] group name, ignored on restore
+
+ // [ 100 : 8 ] file mode
+ snprintf(buf + 100, 8, "%06o ", s.st_mode & ~S_IFMT);
+
+ // [ 108 : 8 ] uid -- ignored in Android format; uids are remapped at restore time
+ // [ 116 : 8 ] gid -- ignored in Android format
+ snprintf(buf + 108, 8, "0%lo", s.st_uid);
+ snprintf(buf + 116, 8, "0%lo", s.st_gid);
+
+ // [ 124 : 12 ] file size in bytes
+ if (s.st_size > 077777777777LL) {
+ // very large files need a pax extended size header
+ needExtended = true;
+ }
+ snprintf(buf + 124, 12, "%011llo", (isdir) ? 0LL : s.st_size);
+
+ // [ 136 : 12 ] last mod time as a UTC time_t
+ snprintf(buf + 136, 12, "%0lo", s.st_mtime);
+
+ // [ 156 : 1 ] link/file type
+ uint8_t type;
+ if (isdir) {
+ type = '5'; // tar magic: '5' == directory
+ } else if (S_ISREG(s.st_mode)) {
+ type = '0'; // tar magic: '0' == normal file
+ } else {
+ LOGW("Error: unknown file mode 0%o [%s]", s.st_mode, filepath.string());
+ goto cleanup;
+ }
+ buf[156] = type;
+
+ // [ 157 : 100 ] name of linked file [not implemented]
+
+ {
+ // Prefix and main relative path. Path lengths have been preflighted.
+ if (packageName.length() > 0) {
+ prefix = "apps/";
+ prefix += packageName;
+ }
+ if (domain.length() > 0) {
+ prefix.appendPath(domain);
+ }
+
+ // pax extended means we don't put in a prefix field, and put a different
+ // string in the basic name field. We can also construct the full path name
+ // out of the substrings we've now built.
+ fullname = prefix;
+ fullname.appendPath(relpath);
+
+ // ustar:
+ // [ 0 : 100 ]; file name/path
+ // [ 345 : 155 ] filename path prefix
+ // We only use the prefix area if fullname won't fit in the path
+ if (fullname.length() > 100) {
+ strncpy(buf, relpath.string(), 100);
+ strncpy(buf + 345, prefix.string(), 155);
+ } else {
+ strncpy(buf, fullname.string(), 100);
+ }
+ }
+
+ // [ 329 : 8 ] and [ 337 : 8 ] devmajor/devminor, not used
+
+ LOGI(" Name: %s", fullname.string());
+
+ // If we're using a pax extended header, build & write that here; lengths are
+ // already preflighted
+ if (needExtended) {
+ char sizeStr[32]; // big enough for a 64-bit unsigned value in decimal
+ char* p = paxData;
+
+ // construct the pax extended header data block
+ memset(paxData, 0, BUFSIZE - (paxData - buf));
+ int len;
+
+ // size header -- calc len in digits by actually rendering the number
+ // to a string - brute force but simple
+ snprintf(sizeStr, sizeof(sizeStr), "%lld", s.st_size);
+ p += write_pax_header_entry(p, "size", sizeStr);
+
+ // fullname was generated above with the ustar paths
+ p += write_pax_header_entry(p, "path", fullname.string());
+
+ // Now we know how big the pax data is
+ int paxLen = p - paxData;
+
+ // Now build the pax *header* templated on the ustar header
+ memcpy(paxHeader, buf, 512);
+
+ String8 leaf = fullname.getPathLeaf();
+ memset(paxHeader, 0, 100); // rewrite the name area
+ snprintf(paxHeader, 100, "PaxHeader/%s", leaf.string());
+ memset(paxHeader + 345, 0, 155); // rewrite the prefix area
+ strncpy(paxHeader + 345, prefix.string(), 155);
+
+ paxHeader[156] = 'x'; // mark it as a pax extended header
+
+ // [ 124 : 12 ] size of pax extended header data
+ memset(paxHeader + 124, 0, 12);
+ snprintf(paxHeader + 124, 12, "%011o", p - paxData);
+
+ // Checksum and write the pax block header
+ calc_tar_checksum(paxHeader);
+ writer->WriteEntityData(paxHeader, 512);
+
+ // Now write the pax data itself
+ int paxblocks = (paxLen + 511) / 512;
+ writer->WriteEntityData(paxData, 512 * paxblocks);
+ }
+
+ // Checksum and write the 512-byte ustar file header block to the output
+ calc_tar_checksum(buf);
+ writer->WriteEntityData(buf, 512);
+
+ // Now write the file data itself, for real files. We honor tar's convention that
+ // only full 512-byte blocks are sent to write().
+ if (!isdir) {
+ off64_t toWrite = s.st_size;
+ while (toWrite > 0) {
+ size_t toRead = (toWrite < BUFSIZE) ? toWrite : BUFSIZE;
+ ssize_t nRead = read(fd, buf, toRead);
+ if (nRead < 0) {
+ err = errno;
+ LOGE("Unable to read file [%s], err=%d (%s)", filepath.string(),
+ err, strerror(err));
+ break;
+ } else if (nRead == 0) {
+ LOGE("EOF but expect %lld more bytes in [%s]", (long long) toWrite,
+ filepath.string());
+ err = EIO;
+ break;
+ }
+
+ // At EOF we might have a short block; NUL-pad that to a 512-byte multiple. This
+ // depends on the OS guarantee that for ordinary files, read() will never return
+ // less than the number of bytes requested.
+ ssize_t partial = (nRead+512) % 512;
+ if (partial > 0) {
+ ssize_t remainder = 512 - partial;
+ memset(buf + nRead, 0, remainder);
+ nRead += remainder;
+ }
+ writer->WriteEntityData(buf, nRead);
+ toWrite -= nRead;
+ }
+ }
+
+cleanup:
+ delete [] buf;
+done:
+ close(fd);
+ return err;
+}
+// end tarfile
+
+
+
#define RESTORE_BUF_SIZE (8*1024)
RestoreHelperBase::RestoreHelperBase()