diff options
Diffstat (limited to 'libs/rs')
194 files changed, 17357 insertions, 7636 deletions
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk index 6f2cd07..3835852 100644 --- a/libs/rs/Android.mk +++ b/libs/rs/Android.mk @@ -23,7 +23,17 @@ include $(BUILD_HOST_EXECUTABLE) # TODO: This should go into build/core/config.mk RSG_GENERATOR:=$(LOCAL_BUILT_MODULE) +# include $(CLEAR_VARS) +# input_data_file := $(LOCAL_PATH)/rslib.bc +# 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 +# include frameworks/compile/slang/SlangData.mk +# include $(BUILD_STATIC_LIBRARY) # Build render script lib ==================== @@ -76,37 +86,44 @@ ifneq ($(TARGET_SIMULATOR),true) LOCAL_SRC_FILES:= \ rsAdapter.cpp \ rsAllocation.cpp \ + rsAnimation.cpp \ rsComponent.cpp \ rsContext.cpp \ rsDevice.cpp \ rsElement.cpp \ - rsFileA3D.cpp \ - rsLight.cpp \ + rsFileA3D.cpp \ + rsFont.cpp \ rsLocklessFifo.cpp \ rsObjectBase.cpp \ rsMatrix.cpp \ - rsMesh.cpp \ - rsNoise.cpp \ + rsMesh.cpp \ + rsMutex.cpp \ rsProgram.cpp \ rsProgramFragment.cpp \ - rsProgramFragmentStore.cpp \ + rsProgramStore.cpp \ rsProgramRaster.cpp \ rsProgramVertex.cpp \ rsSampler.cpp \ rsScript.cpp \ rsScriptC.cpp \ rsScriptC_Lib.cpp \ - rsShaderCache.cpp \ - rsSimpleMesh.cpp \ + rsScriptC_LibCL.cpp \ + rsScriptC_LibGL.cpp \ + rsShaderCache.cpp \ + rsSignal.cpp \ + rsStream.cpp \ rsThreadIO.cpp \ rsType.cpp \ rsVertexArray.cpp -ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) - LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -endif -LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libacc +LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc + +LOCAL_STATIC_LIBRARIES := libdex libft2 + +LOCAL_C_INCLUDES += external/freetype/include external/zlib dalvik +LOCAL_C_INCLUDES += frameworks/compile/libbcc/include + LOCAL_LDLIBS := -lpthread -ldl LOCAL_MODULE:= libRS LOCAL_MODULE_TAGS := optional diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h index d280f50..f160ef1 100644 --- a/libs/rs/RenderScript.h +++ b/libs/rs/RenderScript.h @@ -27,23 +27,27 @@ extern "C" { ////////////////////////////////////////////////////// // +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 * RsSimpleMesh; +typedef void * RsMesh; typedef void * RsType; -typedef void * RsLight; +typedef void * RsObjectBase; typedef void * RsProgram; typedef void * RsProgramVertex; typedef void * RsProgramFragment; -typedef void * RsProgramFragmentStore; +typedef void * RsProgramStore; typedef void * RsProgramRaster; typedef void (* RsBitmapCallback_t)(void *); @@ -53,22 +57,69 @@ enum RsDeviceParam { 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, bool useDepth); +RsContext rsContextCreateGL(RsDevice, uint32_t version, RsSurfaceConfig sc); void rsContextDestroy(RsContext); -void rsObjDestroyOOB(RsContext, void *); -uint32_t rsContextGetMessage(RsContext, void *data, size_t *receiveLen, size_t bufferLen, bool wait); +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, @@ -83,11 +134,17 @@ enum RsDataType { 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_ELEMENT, + 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, @@ -96,24 +153,17 @@ enum RsDataType { RS_TYPE_PROGRAM_FRAGMENT, RS_TYPE_PROGRAM_VERTEX, RS_TYPE_PROGRAM_RASTER, - RS_TYPE_PROGRAM_STORE + RS_TYPE_PROGRAM_STORE, }; enum RsDataKind { RS_KIND_USER, - RS_KIND_COLOR, - RS_KIND_POSITION, - RS_KIND_TEXTURE, - RS_KIND_NORMAL, - RS_KIND_INDEX, - RS_KIND_POINT_SIZE, - - RS_KIND_PIXEL_L, + + RS_KIND_PIXEL_L = 7, RS_KIND_PIXEL_A, RS_KIND_PIXEL_LA, RS_KIND_PIXEL_RGB, RS_KIND_PIXEL_RGBA, - }; enum RsSamplerParam { @@ -121,7 +171,8 @@ enum RsSamplerParam { RS_SAMPLER_MAG_FILTER, RS_SAMPLER_WRAP_S, RS_SAMPLER_WRAP_T, - RS_SAMPLER_WRAP_R + RS_SAMPLER_WRAP_R, + RS_SAMPLER_ANISO }; enum RsSamplerValue { @@ -129,7 +180,13 @@ enum RsSamplerValue { RS_SAMPLER_LINEAR, RS_SAMPLER_LINEAR_MIP_LINEAR, RS_SAMPLER_WRAP, - RS_SAMPLER_CLAMP + RS_SAMPLER_CLAMP, + RS_SAMPLER_LINEAR_MIP_NEAREST, +}; + +enum RsTextureTarget { + RS_TEXTURE_2D, + RS_TEXTURE_CUBE }; enum RsDimension { @@ -190,7 +247,7 @@ enum RsProgramParam { RS_PROGRAM_PARAM_INPUT, RS_PROGRAM_PARAM_OUTPUT, RS_PROGRAM_PARAM_CONSTANT, - RS_PROGRAM_PARAM_TEXTURE_COUNT, + RS_PROGRAM_PARAM_TEXTURE_TYPE, }; enum RsPrimitive { @@ -203,11 +260,112 @@ enum RsPrimitive { }; enum RsError { - RS_ERROR_NONE, - RS_ERROR_BAD_SHADER, - RS_ERROR_BAD_SCRIPT + 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; + +// A3D loading and object update code. +// Should only be called at object creation, not thread safe +RsObjectBase rsaFileA3DGetEntryByIndex(RsContext, uint32_t idx, RsFile); +RsFile rsaFileA3DCreateFromMemory(RsContext, const void *data, uint32_t len); +RsFile rsaFileA3DCreateFromAsset(RsContext, void *asset); +RsFile rsaFileA3DCreateFromFile(RsContext, const char *path); +void rsaFileA3DGetNumIndexEntries(RsContext, int32_t *numEntries, RsFile); +void rsaFileA3DGetIndexEntries(RsContext, RsFileIndexEntry *fileEntries,uint32_t numEntries, RsFile); +void rsaGetName(RsContext, void * obj, const char **name); +// Mesh update functions +void rsaMeshGetVertexBufferCount(RsContext, RsMesh, int32_t *vtxCount); +void rsaMeshGetIndexCount(RsContext, RsMesh, int32_t *idxCount); +void rsaMeshGetVertices(RsContext, RsMesh, RsAllocation *vtxData, uint32_t vtxDataCount); +void rsaMeshGetIndices(RsContext, RsMesh, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount); +// Allocation update +const void* rsaAllocationGetType(RsContext con, RsAllocation va); +// Type update +void rsaTypeGetNativeData(RsContext, RsType, uint32_t *typeData, uint32_t typeDataSize); +// Element update +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); + #ifndef NO_RS_FUNCS #include "rsgApiFuncDecl.h" #endif diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h index 99b8c04..b82eaf1 100644 --- a/libs/rs/RenderScriptEnv.h +++ b/libs/rs/RenderScriptEnv.h @@ -9,12 +9,10 @@ typedef void * RsDevice; typedef void * RsElement; typedef void * RsSampler; typedef void * RsScript; -typedef void * RsSimpleMesh; +typedef void * RsMesh; typedef void * RsType; typedef void * RsProgramFragment; -typedef void * RsProgramFragmentStore; -typedef void * RsLight; - +typedef void * RsProgramStore; typedef struct { float m[16]; @@ -28,4 +26,4 @@ typedef struct { #define RS_PROGRAM_VERTEX_MODELVIEW_OFFSET 0 #define RS_PROGRAM_VERTEX_PROJECTION_OFFSET 16 #define RS_PROGRAM_VERTEX_TEXTURE_OFFSET 32 - +#define RS_PROGRAM_VERTEX_MVP_OFFSET 48 diff --git a/libs/rs/java/Film/Android.mk b/libs/rs/java/Balls/Android.mk index 9e6ed7e..5b65628 100644 --- a/libs/rs/java/Film/Android.mk +++ b/libs/rs/java/Balls/Android.mk @@ -14,14 +14,18 @@ # limitations under the License. # +ifneq ($(TARGET_SIMULATOR),true) + LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript -LOCAL_PACKAGE_NAME := Film +LOCAL_PACKAGE_NAME := Balls include $(BUILD_PACKAGE) + +endif diff --git a/libs/rs/java/Film/AndroidManifest.xml b/libs/rs/java/Balls/AndroidManifest.xml index a5ce8a1..2fffc5f 100644 --- a/libs/rs/java/Film/AndroidManifest.xml +++ b/libs/rs/java/Balls/AndroidManifest.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.film"> - <application android:label="Film"> - <activity android:name="Film" - android:screenOrientation="portrait" - android:theme="@android:style/Theme.Black.NoTitleBar"> + package="com.android.balls"> + <application + android:label="Balls" + android:icon="@drawable/test_pattern"> + <activity android:name="Balls" + android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> diff --git a/libs/rs/java/Balls/res/drawable/flares.png b/libs/rs/java/Balls/res/drawable/flares.png Binary files differnew file mode 100644 index 0000000..3a5c970 --- /dev/null +++ b/libs/rs/java/Balls/res/drawable/flares.png diff --git a/libs/rs/java/Balls/res/drawable/test_pattern.png b/libs/rs/java/Balls/res/drawable/test_pattern.png Binary files differnew file mode 100644 index 0000000..e7d1455 --- /dev/null +++ b/libs/rs/java/Balls/res/drawable/test_pattern.png diff --git a/libs/rs/java/Balls/src/com/android/balls/Balls.java b/libs/rs/java/Balls/src/com/android/balls/Balls.java new file mode 100644 index 0000000..c24e616 --- /dev/null +++ b/libs/rs/java/Balls/src/com/android/balls/Balls.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.balls; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; + +public class Balls extends Activity implements SensorEventListener { + //EventListener mListener = new EventListener(); + + private static final String LOG_TAG = "libRS_jni"; + private static final boolean DEBUG = false; + private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; + + private BallsView mView; + private SensorManager mSensorManager; + + // get the current looper (from your Activity UI thread for instance + + + public void onSensorChanged(SensorEvent event) { + //android.util.Log.d("rs", "sensor: " + event.sensor + ", x: " + event.values[0] + ", y: " + event.values[1] + ", z: " + event.values[2]); + synchronized (this) { + if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { + if(mView != null) { + mView.setAccel(event.values[0], event.values[1], event.values[2]); + } + } + } + } + + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); + + // Create our Preview view and set it as the content of our + // Activity + mView = new BallsView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + mSensorManager.registerListener(this, + mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), + SensorManager.SENSOR_DELAY_FASTEST); + + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mView.resume(); + } + + @Override + protected void onPause() { + super.onPause(); + mView.pause(); + Runtime.getRuntime().exit(0); + } + + @Override + protected void onStop() { + mSensorManager.unregisterListener(this); + super.onStop(); + } + + static void log(String message) { + if (LOG_ENABLED) { + Log.v(LOG_TAG, message); + } + } + + +} + diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java new file mode 100644 index 0000000..50ee921 --- /dev/null +++ b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.balls; + +import android.content.res.Resources; +import android.renderscript.*; +import android.util.Log; + +public class BallsRS { + public static final int PART_COUNT = 900; + + public BallsRS() { + } + + private Resources mRes; + private RenderScriptGL mRS; + private ScriptC_balls mScript; + private ScriptC_ball_physics mPhysicsScript; + private ProgramFragment mPFLines; + private ProgramFragment mPFPoints; + private ProgramVertex mPV; + private ScriptField_Point mPoints; + private ScriptField_VpConsts mVpConsts; + + void updateProjectionMatrices() { + mVpConsts = new ScriptField_VpConsts(mRS, 1, + Allocation.USAGE_SCRIPT | + Allocation.USAGE_GRAPHICS_CONSTANTS); + ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item(); + Matrix4f mvp = new Matrix4f(); + mvp.loadOrtho(0, mRS.getWidth(), mRS.getHeight(), 0, -1, 1); + i.MVP = mvp; + mVpConsts.set(i, 0, true); + } + + private void createProgramVertex() { + updateProjectionMatrices(); + + ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS); + String t = "varying vec4 varColor;\n" + + "void main() {\n" + + " vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" + + " pos.xy = ATTRIB_position;\n" + + " gl_Position = UNI_MVP * pos;\n" + + " varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" + + " gl_PointSize = ATTRIB_size;\n" + + "}\n"; + sb.setShader(t); + sb.addConstant(mVpConsts.getType()); + sb.addInput(mPoints.getElement()); + ProgramVertex pvs = sb.create(); + pvs.bindConstants(mVpConsts.getAllocation(), 0); + mRS.bindProgramVertex(pvs); + } + + private Allocation loadTexture(int id) { + final Allocation allocation = + Allocation.createFromBitmapResource(mRS, mRes, + id, Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_GRAPHICS_TEXTURE); + return allocation; + } + + ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) { + ProgramStore.Builder builder = new ProgramStore.Builder(rs); + builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); + builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ONE); + builder.setDitherEnabled(false); + builder.setDepthMaskEnabled(false); + return builder.create(); + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + + ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs); + pfb.setPointSpriteTexCoordinateReplacement(true); + pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE, + ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); + pfb.setVaryingColor(true); + mPFPoints = pfb.create(); + + pfb = new ProgramFragmentFixedFunction.Builder(rs); + pfb.setVaryingColor(true); + mPFLines = pfb.create(); + + android.util.Log.e("rs", "Load texture"); + mPFPoints.bindTexture(loadTexture(R.drawable.flares), 0); + + mPoints = new ScriptField_Point(mRS, PART_COUNT, Allocation.USAGE_SCRIPT); + + Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS); + smb.addVertexAllocation(mPoints.getAllocation()); + smb.addIndexSetType(Mesh.Primitive.POINT); + Mesh smP = smb.create(); + + mPhysicsScript = new ScriptC_ball_physics(mRS, mRes, R.raw.ball_physics); + + mScript = new ScriptC_balls(mRS, mRes, R.raw.balls); + mScript.set_partMesh(smP); + mScript.set_physics_script(mPhysicsScript); + mScript.bind_point(mPoints); + mScript.bind_balls1(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT)); + mScript.bind_balls2(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT)); + + mScript.set_gPFLines(mPFLines); + mScript.set_gPFPoints(mPFPoints); + createProgramVertex(); + + mRS.bindProgramStore(BLEND_ADD_DEPTH_NONE(mRS)); + + mPhysicsScript.set_gMinPos(new Float2(5, 5)); + mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5)); + + mScript.invoke_initParts(width, height); + + mRS.bindRootScript(mScript); + } + + public void newTouchPosition(float x, float y, float pressure, int id) { + mPhysicsScript.invoke_touch(x, y, pressure, id); + } + + public void setAccel(float x, float y) { + mPhysicsScript.set_gGravityVector(new Float2(x, y)); + } + +} diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsView.java b/libs/rs/java/Balls/src/com/android/balls/BallsView.java new file mode 100644 index 0000000..4442eec --- /dev/null +++ b/libs/rs/java/Balls/src/com/android/balls/BallsView.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.balls; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class BallsView extends RSSurfaceView { + + public BallsView(Context context) { + super(context); + //setFocusable(true); + } + + private RenderScriptGL mRS; + private BallsRS mRender; + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); + mRender = new BallsRS(); + mRender.init(mRS, getResources(), w, h); + } + mRender.updateProjectionMatrices(); + } + + @Override + protected void onDetachedFromWindow() { + if(mRS != null) { + mRS = null; + destroyRenderScriptGL(); + } + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) + { + int act = ev.getActionMasked(); + if (act == ev.ACTION_UP) { + mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0)); + return false; + } else if (act == MotionEvent.ACTION_POINTER_UP) { + // only one pointer going up, we can get the index like this + int pointerIndex = ev.getActionIndex(); + int pointerId = ev.getPointerId(pointerIndex); + mRender.newTouchPosition(0, 0, 0, pointerId); + return false; + } + int count = ev.getHistorySize(); + int pcount = ev.getPointerCount(); + + for (int p=0; p < pcount; p++) { + int id = ev.getPointerId(p); + mRender.newTouchPosition(ev.getX(p), + ev.getY(p), + ev.getPressure(p), + id); + + for (int i=0; i < count; i++) { + mRender.newTouchPosition(ev.getHistoricalX(p, i), + ev.getHistoricalY(p, i), + ev.getHistoricalPressure(p, i), + id); + } + } + return true; + } + + void setAccel(float x, float y, float z) { + if (mRender == null) { + return; + } + mRender.setAccel(x, -y); + } + +} + + diff --git a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs new file mode 100644 index 0000000..ff38be5 --- /dev/null +++ b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs @@ -0,0 +1,146 @@ +#pragma version(1) +#pragma rs java_package_name(com.android.balls) + +#include "balls.rsh" + +float2 gGravityVector = {0.f, 9.8f}; + +float2 gMinPos = {0.f, 0.f}; +float2 gMaxPos = {1280.f, 700.f}; + +static float2 touchPos[10]; +static float touchPressure[10]; + +void touch(float x, float y, float pressure, int id) { + if (id >= 10) { + return; + } + + touchPos[id].x = x; + touchPos[id].y = y; + touchPressure[id] = pressure; +} + +void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint32_t x) { + float2 fv = {0, 0}; + float2 pos = ballIn->position; + + int arcID = -1; + float arcInvStr = 100000; + + const Ball_t * bPtr = rsGetElementAt(ctl->ain, 0); + for (uint32_t xin = 0; xin < ctl->dimX; xin++) { + float2 vec = bPtr[xin].position - pos; + float2 vec2 = vec * vec; + float len2 = vec2.x + vec2.y; + + if (len2 < 10000) { + //float minDist = ballIn->size + bPtr[xin].size; + float forceScale = ballIn->size * bPtr[xin].size; + forceScale *= forceScale; + + if (len2 > 16 /* (minDist*minDist)*/) { + // Repulsion + float len = sqrt(len2); + fv -= (vec / (len * len * len)) * 20000.f * forceScale; + } else { + if (len2 < 1) { + if (xin == x) { + continue; + } + ballOut->delta = 0.f; + ballOut->position = ballIn->position; + if (xin > x) { + ballOut->position.x += 1.f; + } else { + ballOut->position.x -= 1.f; + } + //ballOut->color.rgb = 1.f; + //ballOut->arcID = -1; + //ballOut->arcStr = 0; + return; + } + // Collision + float2 axis = normalize(vec); + float e1 = dot(axis, ballIn->delta); + float e2 = dot(axis, bPtr[xin].delta); + float e = (e1 - e2) * 0.45f; + if (e1 > 0) { + fv -= axis * e; + } else { + fv += axis * e; + } + } + } + } + + fv /= ballIn->size * ballIn->size * ballIn->size; + fv -= gGravityVector * 4.f; + fv *= ctl->dt; + + for (int i=0; i < 10; i++) { + if (touchPressure[i] > 0.1f) { + float2 vec = touchPos[i] - ballIn->position; + float2 vec2 = vec * vec; + float len2 = max(2.f, vec2.x + vec2.y); + fv -= (vec / len2) * touchPressure[i] * 300.f; + } + } + + ballOut->delta = (ballIn->delta * (1.f - 0.004f)) + fv; + ballOut->position = ballIn->position + (ballOut->delta * ctl->dt); + + const float wallForce = 400.f; + if (ballOut->position.x > (gMaxPos.x - 20.f)) { + float d = gMaxPos.x - ballOut->position.x; + if (d < 0.f) { + if (ballOut->delta.x > 0) { + ballOut->delta.x *= -0.7; + } + ballOut->position.x = gMaxPos.x; + } else { + ballOut->delta.x -= min(wallForce / (d * d), 10.f); + } + } + + if (ballOut->position.x < (gMinPos.x + 20.f)) { + float d = ballOut->position.x - gMinPos.x; + if (d < 0.f) { + if (ballOut->delta.x < 0) { + ballOut->delta.x *= -0.7; + } + ballOut->position.x = gMinPos.x + 1.f; + } else { + ballOut->delta.x += min(wallForce / (d * d), 10.f); + } + } + + if (ballOut->position.y > (gMaxPos.y - 20.f)) { + float d = gMaxPos.y - ballOut->position.y; + if (d < 0.f) { + if (ballOut->delta.y > 0) { + ballOut->delta.y *= -0.7; + } + ballOut->position.y = gMaxPos.y; + } else { + ballOut->delta.y -= min(wallForce / (d * d), 10.f); + } + } + + if (ballOut->position.y < (gMinPos.y + 20.f)) { + float d = ballOut->position.y - gMinPos.y; + if (d < 0.f) { + if (ballOut->delta.y < 0) { + ballOut->delta.y *= -0.7; + } + ballOut->position.y = gMinPos.y + 1.f; + } else { + ballOut->delta.y += min(wallForce / (d * d * d), 10.f); + } + } + + ballOut->size = ballIn->size; + + //rsDebug("physics pos out", ballOut->position); +} + diff --git a/libs/rs/java/Balls/src/com/android/balls/balls.rs b/libs/rs/java/Balls/src/com/android/balls/balls.rs new file mode 100644 index 0000000..fed9963 --- /dev/null +++ b/libs/rs/java/Balls/src/com/android/balls/balls.rs @@ -0,0 +1,85 @@ +#pragma version(1) +#pragma rs java_package_name(com.android.balls) +#include "rs_graphics.rsh" + +#include "balls.rsh" + +#pragma stateVertex(parent) +#pragma stateStore(parent) + +rs_program_fragment gPFPoints; +rs_program_fragment gPFLines; +rs_mesh partMesh; + +typedef struct __attribute__((packed, aligned(4))) Point { + float2 position; + float size; +} Point_t; +Point_t *point; + +typedef struct VpConsts { + rs_matrix4x4 MVP; +} VpConsts_t; +VpConsts_t *vpConstants; + +rs_script physics_script; + +Ball_t *balls1; +Ball_t *balls2; + +static int frame = 0; + +void initParts(int w, int h) +{ + uint32_t dimX = rsAllocationGetDimX(rsGetAllocation(balls1)); + + for (uint32_t ct=0; ct < dimX; ct++) { + balls1[ct].position.x = rsRand(0.f, (float)w); + balls1[ct].position.y = rsRand(0.f, (float)h); + balls1[ct].delta.x = 0.f; + balls1[ct].delta.y = 0.f; + balls1[ct].size = 1.f; + + float r = rsRand(100.f); + if (r > 90.f) { + balls1[ct].size += pow(10.f, rsRand(0.f, 2.f)) * 0.07; + } + } +} + + + +int root() { + rsgClearColor(0.f, 0.f, 0.f, 1.f); + + BallControl_t bc = {0}; + Ball_t *bout; + + if (frame & 1) { + rsSetObject(&bc.ain, rsGetAllocation(balls2)); + rsSetObject(&bc.aout, rsGetAllocation(balls1)); + bout = balls2; + } else { + rsSetObject(&bc.ain, rsGetAllocation(balls1)); + rsSetObject(&bc.aout, rsGetAllocation(balls2)); + bout = balls1; + } + + bc.dimX = rsAllocationGetDimX(bc.ain); + bc.dt = 1.f / 30.f; + + rsForEach(physics_script, bc.ain, bc.aout, &bc); + + for (uint32_t ct=0; ct < bc.dimX; ct++) { + point[ct].position = bout[ct].position; + point[ct].size = 6.f /*+ bout[ct].color.g * 6.f*/ * bout[ct].size; + } + + frame++; + rsgBindProgramFragment(gPFPoints); + rsgDrawMesh(partMesh); + rsClearObject(&bc.ain); + rsClearObject(&bc.aout); + return 1; +} + diff --git a/libs/rs/java/Balls/src/com/android/balls/balls.rsh b/libs/rs/java/Balls/src/com/android/balls/balls.rsh new file mode 100644 index 0000000..fc886f9 --- /dev/null +++ b/libs/rs/java/Balls/src/com/android/balls/balls.rsh @@ -0,0 +1,18 @@ + +typedef struct __attribute__((packed, aligned(4))) Ball { + float2 delta; + float2 position; + //float3 color; + float size; + //int arcID; + //float arcStr; +} Ball_t; +Ball_t *balls; + + +typedef struct BallControl { + uint32_t dimX; + rs_allocation ain; + rs_allocation aout; + float dt; +} BallControl_t; diff --git a/libs/rs/java/Film/res/drawable/p01.png b/libs/rs/java/Film/res/drawable/p01.png Binary files differdeleted file mode 100644 index a9b9bdb..0000000 --- a/libs/rs/java/Film/res/drawable/p01.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p02.png b/libs/rs/java/Film/res/drawable/p02.png Binary files differdeleted file mode 100644 index 8162c82..0000000 --- a/libs/rs/java/Film/res/drawable/p02.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p03.png b/libs/rs/java/Film/res/drawable/p03.png Binary files differdeleted file mode 100644 index e3e26c0..0000000 --- a/libs/rs/java/Film/res/drawable/p03.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p04.png b/libs/rs/java/Film/res/drawable/p04.png Binary files differdeleted file mode 100644 index daee603..0000000 --- a/libs/rs/java/Film/res/drawable/p04.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p05.png b/libs/rs/java/Film/res/drawable/p05.png Binary files differdeleted file mode 100644 index fac5248..0000000 --- a/libs/rs/java/Film/res/drawable/p05.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p06.png b/libs/rs/java/Film/res/drawable/p06.png Binary files differdeleted file mode 100644 index 3b51261..0000000 --- a/libs/rs/java/Film/res/drawable/p06.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p07.png b/libs/rs/java/Film/res/drawable/p07.png Binary files differdeleted file mode 100644 index d8bd938..0000000 --- a/libs/rs/java/Film/res/drawable/p07.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p08.png b/libs/rs/java/Film/res/drawable/p08.png Binary files differdeleted file mode 100644 index ef175e8..0000000 --- a/libs/rs/java/Film/res/drawable/p08.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p09.png b/libs/rs/java/Film/res/drawable/p09.png Binary files differdeleted file mode 100644 index 7bf3874..0000000 --- a/libs/rs/java/Film/res/drawable/p09.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p10.png b/libs/rs/java/Film/res/drawable/p10.png Binary files differdeleted file mode 100644 index 908827d..0000000 --- a/libs/rs/java/Film/res/drawable/p10.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p11.png b/libs/rs/java/Film/res/drawable/p11.png Binary files differdeleted file mode 100644 index 1289f71..0000000 --- a/libs/rs/java/Film/res/drawable/p11.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p12.png b/libs/rs/java/Film/res/drawable/p12.png Binary files differdeleted file mode 100644 index e1af16a..0000000 --- a/libs/rs/java/Film/res/drawable/p12.png +++ /dev/null diff --git a/libs/rs/java/Film/res/drawable/p13.png b/libs/rs/java/Film/res/drawable/p13.png Binary files differdeleted file mode 100644 index d08bcbe..0000000 --- a/libs/rs/java/Film/res/drawable/p13.png +++ /dev/null diff --git a/libs/rs/java/Film/res/raw/filmimage.c b/libs/rs/java/Film/res/raw/filmimage.c deleted file mode 100644 index d154c68..0000000 --- a/libs/rs/java/Film/res/raw/filmimage.c +++ /dev/null @@ -1,110 +0,0 @@ -// Fountain test script - -#pragma version(1) -#pragma stateVertex(orthoWindow) -#pragma stateRaster(flat) -#pragma stateFragment(PgmFragBackground) -#pragma stateStore(MyBlend) - - -int main(void* con, int ft, int launchID) { - int count, touch, x, y, rate, maxLife, lifeShift; - int life; - int ct, ct2; - int newPart; - int drawCount; - int dx, dy, idx; - int posx,posy; - int c; - int srcIdx; - int dstIdx; - - count = loadI32(con, 0, 1); - touch = loadI32(con, 0, 2); - x = loadI32(con, 0, 3); - y = loadI32(con, 0, 4); - - rate = 4; - maxLife = (count / rate) - 1; - lifeShift = 0; - { - life = maxLife; - while (life > 255) { - life = life >> 1; - lifeShift ++; - } - } - - drawRect(con, 0, 256, 0, 512); - contextBindProgramFragment(con, NAMED_PgmFragParts); - - if (touch) { - newPart = loadI32(con, 2, 0); - for (ct2=0; ct2<rate; ct2++) { - dx = scriptRand(con, 0x10000) - 0x8000; - dy = scriptRand(con, 0x10000) - 0x8000; - - idx = newPart * 5 + 1; - storeI32(con, 2, idx, dx); - storeI32(con, 2, idx + 1, dy); - storeI32(con, 2, idx + 2, maxLife); - storeI32(con, 2, idx + 3, x << 16); - storeI32(con, 2, idx + 4, y << 16); - - newPart++; - if (newPart >= count) { - newPart = 0; - } - } - storeI32(con, 2, 0, newPart); - } - - drawCount = 0; - for (ct=0; ct < count; ct++) { - srcIdx = ct * 5 + 1; - - dx = loadI32(con, 2, srcIdx); - dy = loadI32(con, 2, srcIdx + 1); - life = loadI32(con, 2, srcIdx + 2); - posx = loadI32(con, 2, srcIdx + 3); - posy = loadI32(con, 2, srcIdx + 4); - - if (life) { - if (posy < (480 << 16)) { - dstIdx = drawCount * 9; - c = 0xffafcf | ((life >> lifeShift) << 24); - - storeU32(con, 1, dstIdx, c); - storeI32(con, 1, dstIdx + 1, posx); - storeI32(con, 1, dstIdx + 2, posy); - - storeU32(con, 1, dstIdx + 3, c); - storeI32(con, 1, dstIdx + 4, posx + 0x10000); - storeI32(con, 1, dstIdx + 5, posy + dy * 4); - - storeU32(con, 1, dstIdx + 6, c); - storeI32(con, 1, dstIdx + 7, posx - 0x10000); - storeI32(con, 1, dstIdx + 8, posy + dy * 4); - drawCount ++; - } else { - if (dy > 0) { - dy = (-dy) >> 1; - } - } - - posx = posx + dx; - posy = posy + dy; - dy = dy + 0x400; - life --; - - //storeI32(con, 2, srcIdx, dx); - storeI32(con, 2, srcIdx + 1, dy); - storeI32(con, 2, srcIdx + 2, life); - storeI32(con, 2, srcIdx + 3, posx); - storeI32(con, 2, srcIdx + 4, posy); - } - } - - drawTriangleArray(con, NAMED_PartBuffer, drawCount); - return 1; -} diff --git a/libs/rs/java/Film/res/raw/filmstrip.c b/libs/rs/java/Film/res/raw/filmstrip.c deleted file mode 100644 index bf75675..0000000 --- a/libs/rs/java/Film/res/raw/filmstrip.c +++ /dev/null @@ -1,94 +0,0 @@ -// Fountain test script - -#pragma version(1) -#pragma stateVertex(PVBackground) -#pragma stateFragment(PFBackground) -#pragma stateStore(PSBackground) - -#define STATE_TRIANGLE_OFFSET_COUNT 0 -#define STATE_LAST_FOCUS 1 - - -// The script enviroment has 3 env allocations. -// bank0: (r) The enviroment structure -// bank1: (r) The position information -// bank2: (rw) The temporary texture state - -int lastFocus; - -int main(int index) -{ - float mat1[16]; - - float trans = Pos->translate; - float rot = Pos->rotate; - - matrixLoadScale(mat1, 2.f, 2.f, 2.f); - matrixTranslate(mat1, 0.f, 0.f, trans); - matrixRotate(mat1, 90.f, 0.f, 0.f, 1.f); - matrixRotate(mat1, rot, 1.f, 0.f, 0.f); - vpLoadModelMatrix(mat1); - - // Draw the lighting effect in the strip and fill the Z buffer. - drawSimpleMesh(NAMED_mesh); - - // Start of images. - bindProgramStore(NAMED_PSImages); - bindProgramFragment(NAMED_PFImages); - bindProgramVertex(NAMED_PVImages); - - float focusPos = Pos->focus; - int focusID = 0; - int lastFocusID = loadI32(2, STATE_LAST_FOCUS); - int imgCount = 13; - - if (trans > (-.3f)) { - focusID = -1.0f - focusPos; - if (focusID >= imgCount) { - focusID = -1; - } - } else { - focusID = -1; - } - - /* - if (focusID != lastFocusID) { - if (lastFocusID >= 0) { - uploadToTexture(con, env->tex[lastFocusID], 1); - } - if (focusID >= 0) { - uploadToTexture(con, env->tex[focusID], 0); - } - } - */ - lastFocus = focusID; - - int triangleOffsetsCount = Pos->triangleOffsetCount; - - int imgId = 0; - for (imgId=1; imgId <= imgCount; imgId++) { - float pos = focusPos + imgId + 0.4f; - int offset = (int)floorf(pos * 2.f); - pos = pos - 0.75f; - - offset = offset + triangleOffsetsCount / 2; - if (!((offset < 0) || (offset >= triangleOffsetsCount))) { - int start = offset -2; - int end = offset + 2; - - if (start < 0) { - start = 0; - } - if (end >= triangleOffsetsCount) { - end = triangleOffsetsCount-1; - } - - bindTexture(NAMED_PFImages, 0, loadI32(0, imgId - 1)); - matrixLoadTranslate(mat1, -pos - loadF(5, triangleOffsetsCount / 2), 0, 0); - vpLoadTextureMatrix(mat1); - drawSimpleMeshRange(NAMED_mesh, loadI32(4, start), (loadI32(4, end) - loadI32(4, start))); - } - } - return 0; -} - diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java deleted file mode 100644 index 7d04502..0000000 --- a/libs/rs/java/Film/src/com/android/film/FilmRS.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.film; - -import java.io.Writer; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.util.Log; - -import android.renderscript.*; - -public class FilmRS { - class StripPosition { - public float translate; - public float rotate; - public float focus; - public int triangleOffsetCount; - } - StripPosition mPos = new StripPosition(); - - - private final int STATE_LAST_FOCUS = 1; - - public FilmRS() { - } - - public void init(RenderScriptGL rs, Resources res, int width, int height) { - mRS = rs; - mRes = res; - initRS(); - } - - public void setFilmStripPosition(int x, int y) - { - if (x < 50) { - x = 50; - } - if (x > 270) { - x = 270; - } - - float anim = ((float)x-50) / 270.f; - mPos.translate = 2f * anim + 0.5f; // translation - mPos.rotate = (anim * 40); // rotation - mPos.focus = ((float)y) / 16.f - 10.f; // focusPos - mPos.triangleOffsetCount = mFSM.mTriangleOffsetsCount; - mAllocPos.data(mPos); - } - - - private Resources mRes; - private RenderScriptGL mRS; - private Script mScriptStrip; - private Script mScriptImage; - private Sampler mSampler; - private ProgramStore mPSBackground; - private ProgramStore mPSImages; - private ProgramFragment mPFBackground; - private ProgramFragment mPFImages; - private ProgramVertex mPVBackground; - private ProgramVertex mPVImages; - private ProgramVertex.MatrixAllocation mPVA; - private Type mStripPositionType; - - private Allocation mImages[]; - private Allocation mAllocIDs; - private Allocation mAllocPos; - private Allocation mAllocState; - private Allocation mAllocPV; - private Allocation mAllocOffsetsTex; - private Allocation mAllocOffsets; - - private SimpleMesh mMesh; - private Light mLight; - - private FilmStripMesh mFSM; - - private int[] mBufferIDs; - private float[] mBufferPos = new float[3]; - private int[] mBufferState; - - private void initPFS() { - ProgramStore.Builder b = new ProgramStore.Builder(mRS, null, null); - - b.setDepthFunc(ProgramStore.DepthFunc.LESS); - b.setDitherEnable(true); - b.setDepthMask(true); - mPSBackground = b.create(); - mPSBackground.setName("PSBackground"); - - b.setDepthFunc(ProgramStore.DepthFunc.EQUAL); - b.setDitherEnable(false); - b.setDepthMask(false); - b.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, - ProgramStore.BlendDstFunc.ONE); - mPSImages = b.create(); - mPSImages.setName("PSImages"); - } - - private void initPF() { - Sampler.Builder bs = new Sampler.Builder(mRS); - bs.setMin(Sampler.Value.LINEAR);//_MIP_LINEAR); - bs.setMag(Sampler.Value.LINEAR); - bs.setWrapS(Sampler.Value.CLAMP); - bs.setWrapT(Sampler.Value.WRAP); - mSampler = bs.create(); - - ProgramFragment.Builder b = new ProgramFragment.Builder(mRS); - mPFBackground = b.create(); - mPFBackground.setName("PFBackground"); - - b = new ProgramFragment.Builder(mRS); - b.setTexture(ProgramFragment.Builder.EnvMode.REPLACE, - ProgramFragment.Builder.Format.RGBA, 0); - mPFImages = b.create(); - mPFImages.bindSampler(mSampler, 0); - mPFImages.setName("PFImages"); - } - - private void initPV() { - mLight = (new Light.Builder(mRS)).create(); - mLight.setPosition(0, -0.5f, -1.0f); - - ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null); - //pvb.addLight(mLight); - mPVBackground = pvb.create(); - mPVBackground.setName("PVBackground"); - - pvb = new ProgramVertex.Builder(mRS, null, null); - pvb.setTextureMatrixEnable(true); - mPVImages = pvb.create(); - mPVImages.setName("PVImages"); - } - - private void loadImages() { - mBufferIDs = new int[13]; - mImages = new Allocation[13]; - mAllocIDs = Allocation.createSized(mRS, - Element.createUser(mRS, Element.DataType.FLOAT_32), - mBufferIDs.length); - - Element ie = Element.createPixel(mRS, Element.DataType.UNSIGNED_5_6_5, Element.DataKind.PIXEL_RGB); - mImages[0] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p01, ie, true); - mImages[1] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p02, ie, true); - mImages[2] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p03, ie, true); - mImages[3] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p04, ie, true); - mImages[4] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p05, ie, true); - mImages[5] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p06, ie, true); - mImages[6] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p07, ie, true); - mImages[7] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p08, ie, true); - mImages[8] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p09, ie, true); - mImages[9] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p10, ie, true); - mImages[10] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p11, ie, true); - mImages[11] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p12, ie, true); - mImages[12] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p13, ie, true); - - int black[] = new int[1024]; - for(int ct=0; ct < mImages.length; ct++) { - Allocation.Adapter2D a = mImages[ct].createAdapter2D(); - - int size = 512; - int mip = 0; - while(size >= 2) { - a.subData(0, 0, 2, size, black); - a.subData(size-2, 0, 2, size, black); - a.subData(0, 0, size, 2, black); - a.subData(0, size-2, size, 2, black); - size >>= 1; - mip++; - a.setConstraint(Dimension.LOD, mip); - } - - mImages[ct].uploadToTexture(1); - mBufferIDs[ct] = mImages[ct].getID(); - } - mAllocIDs.data(mBufferIDs); - } - - private void initState() - { - mBufferState = new int[10]; - mAllocState = Allocation.createSized(mRS, - Element.createUser(mRS, Element.DataType.FLOAT_32), - mBufferState.length); - mBufferState[STATE_LAST_FOCUS] = -1; - mAllocState.data(mBufferState); - } - - private void initRS() { - mFSM = new FilmStripMesh(); - mMesh = mFSM.init(mRS); - mMesh.setName("mesh"); - - initPFS(); - initPF(); - initPV(); - - Log.e("rs", "Done loading named"); - - mStripPositionType = Type.createFromClass(mRS, StripPosition.class, 1); - - ScriptC.Builder sb = new ScriptC.Builder(mRS); - sb.setScript(mRes, R.raw.filmstrip); - sb.setRoot(true); - sb.setType(mStripPositionType, "Pos", 1); - mScriptStrip = sb.create(); - mScriptStrip.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); - - mAllocPos = Allocation.createTyped(mRS, mStripPositionType); - - loadImages(); - initState(); - - mPVA = new ProgramVertex.MatrixAllocation(mRS); - mPVBackground.bindAllocation(mPVA); - mPVImages.bindAllocation(mPVA); - mPVA.setupProjectionNormalized(320, 480); - - - mScriptStrip.bindAllocation(mAllocIDs, 0); - mScriptStrip.bindAllocation(mAllocPos, 1); - mScriptStrip.bindAllocation(mAllocState, 2); - mScriptStrip.bindAllocation(mPVA.mAlloc, 3); - - - mAllocOffsets = Allocation.createSized(mRS, - Element.createUser(mRS, Element.DataType.SIGNED_32), mFSM.mTriangleOffsets.length); - mAllocOffsets.data(mFSM.mTriangleOffsets); - mScriptStrip.bindAllocation(mAllocOffsets, 4); - - mAllocOffsetsTex = Allocation.createSized(mRS, - Element.createUser(mRS, Element.DataType.FLOAT_32), mFSM.mTriangleOffsetsTex.length); - mAllocOffsetsTex.data(mFSM.mTriangleOffsetsTex); - mScriptStrip.bindAllocation(mAllocOffsetsTex, 5); - - setFilmStripPosition(0, 0); - mRS.contextBindRootScript(mScriptStrip); - } -} - - - diff --git a/libs/rs/java/Film/src/com/android/film/FilmStripMesh.java b/libs/rs/java/Film/src/com/android/film/FilmStripMesh.java deleted file mode 100644 index 448cce0..0000000 --- a/libs/rs/java/Film/src/com/android/film/FilmStripMesh.java +++ /dev/null @@ -1,259 +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. - */ - - -package com.android.film; - -import java.io.Writer; -import java.lang.Math; -import android.util.Log; - -import android.renderscript.RenderScript; -import android.renderscript.SimpleMesh; - - -class FilmStripMesh { - - class Vertex { - float nx; - float ny; - float nz; - float s; - float t; - float x; - float y; - float z; - - Vertex() { - nx = 0; - ny = 0; - nz = 0; - s = 0; - t = 0; - x = 0; - y = 0; - z = 0; - } - - void xyz(float _x, float _y, float _z) { - x = _x; - y = _y; - z = _z; - } - - void nxyz(float _x, float _y, float _z) { - nx = _x; - ny = _y; - nz = _z; - } - - void st(float _s, float _t) { - s = _s; - t = _t; - } - - void computeNorm(Vertex v1, Vertex v2) { - float dx = v1.x - v2.x; - float dy = v1.y - v2.y; - float dz = v1.z - v2.z; - float len = (float)java.lang.Math.sqrt(dx*dx + dy*dy + dz*dz); - dx /= len; - dy /= len; - dz /= len; - - nx = dx * dz; - ny = dy * dz; - nz = (float)java.lang.Math.sqrt(dx*dx + dy*dy); - - len = (float)java.lang.Math.sqrt(nx*nx + ny*ny + nz*nz); - nx /= len; - ny /= len; - nz /= len; - } - } - - int[] mTriangleOffsets; - float[] mTriangleOffsetsTex; - int mTriangleOffsetsCount; - - SimpleMesh init(RenderScript rs) - { - float vtx[] = new float[] { - 60.431003f, 124.482050f, - 60.862074f, 120.872604f, - 61.705303f, 117.336662f, - 62.949505f, 113.921127f, - 64.578177f, 110.671304f, - 66.569716f, 107.630302f, - 68.897703f, 104.838457f, - 71.531259f, 102.332803f, - 74.435452f, 100.146577f, - 77.571757f, 98.308777f, - 80.898574f, 96.843781f, - 84.371773f, 95.771023f, - 87.945283f, 95.104731f, - 98.958994f, 95.267098f, - 109.489523f, 98.497596f, - 118.699582f, 104.539366f, - 125.856872f, 112.912022f, - 130.392311f, 122.949849f, - 131.945283f, 133.854731f, - 130.392311f, 144.759613f, - 125.856872f, 154.797439f, - 118.699582f, 163.170096f, - 109.489523f, 169.211866f, - 98.958994f, 172.442364f, - 87.945283f, 172.604731f, - 72.507313f, 172.672927f, - 57.678920f, 168.377071f, - 44.668135f, 160.067134f, - 34.534908f, 148.420104f, - 28.104767f, 134.384831f, - 25.901557f, 119.104731f, - 28.104767f, 103.824631f, - 34.534908f, 89.789358f, - 44.668135f, 78.142327f, - 57.678920f, 69.832390f, - 72.507313f, 65.536534f, - 87.945283f, 65.604731f, - 106.918117f, 65.688542f, - 125.141795f, 60.409056f, - 141.131686f, 50.196376f, - 153.585137f, 35.882502f, - 161.487600f, 18.633545f, - 164.195283f, -0.145269f, - 161.487600f, -18.924084f, - 153.585137f, -36.173040f, - 141.131686f, -50.486914f, - 125.141795f, -60.699594f, - 106.918117f, -65.979081f, - 87.945283f, -65.895269f, - 80f, -65.895269f, - 60f, -65.895269f, - 40f, -65.895269f, - 20f, -65.895269f, - 0f, -65.895269f, - -20f, -65.895269f, - -40f, -65.895269f, - -60f, -65.895269f, - -80f, -65.895269f, - -87.945283f, -65.895269f, - -106.918117f, -65.979081f, - -125.141795f, -60.699594f, - -141.131686f, -50.486914f, - -153.585137f, -36.173040f, - -161.487600f, -18.924084f, - -164.195283f, -0.145269f, - -161.487600f, 18.633545f, - -153.585137f, 35.882502f, - -141.131686f, 50.196376f, - -125.141795f, 60.409056f, - -106.918117f, 65.688542f, - -87.945283f, 65.604731f, - -72.507313f, 65.536534f, - -57.678920f, 69.832390f, - -44.668135f, 78.142327f, - -34.534908f, 89.789358f, - -28.104767f, 103.824631f, - -25.901557f, 119.104731f, - -28.104767f, 134.384831f, - -34.534908f, 148.420104f, - -44.668135f, 160.067134f, - -57.678920f, 168.377071f, - -72.507313f, 172.672927f, - -87.945283f, 172.604731f, - -98.958994f, 172.442364f, - -109.489523f, 169.211866f, - -118.699582f, 163.170096f, - -125.856872f, 154.797439f, - -130.392311f, 144.759613f, - -131.945283f, 133.854731f, - -130.392311f, 122.949849f, - -125.856872f, 112.912022f, - -118.699582f, 104.539366f, - -109.489523f, 98.497596f, - -98.958994f, 95.267098f, - -87.945283f, 95.104731f, - -84.371773f, 95.771023f, - -80.898574f, 96.843781f, - -77.571757f, 98.308777f, - -74.435452f, 100.146577f, - -71.531259f, 102.332803f, - -68.897703f, 104.838457f, - -66.569716f, 107.630302f, - -64.578177f, 110.671304f, - -62.949505f, 113.921127f, - -61.705303f, 117.336662f, - -60.862074f, 120.872604f, - -60.431003f, 124.482050f - }; - - - mTriangleOffsets = new int[64]; - mTriangleOffsetsTex = new float[64]; - - mTriangleOffsets[0] = 0; - mTriangleOffsetsCount = 1; - - Vertex t = new Vertex(); - t.nxyz(1, 0, 0); - int count = vtx.length / 2; - - SimpleMesh.TriangleMeshBuilder tm = new SimpleMesh.TriangleMeshBuilder( - rs, 3, - SimpleMesh.TriangleMeshBuilder.NORMAL | SimpleMesh.TriangleMeshBuilder.TEXTURE_0); - - float runningS = 0; - for (int ct=0; ct < (count-1); ct++) { - t.x = -vtx[ct*2] / 100.f; - t.z = vtx[ct*2+1] / 100.f; - t.s = runningS; - t.nx = (vtx[ct*2+3] - vtx[ct*2 +1]); - t.ny = (vtx[ct*2+2] - vtx[ct*2 ]); - float len = (float)java.lang.Math.sqrt(t.nx * t.nx + t.ny * t.ny); - runningS += len / 100; - t.nx /= len; - t.ny /= len; - t.y = -0.5f; - t.t = 0; - tm.setNormal(t.nx, t.ny, t.nz); - tm.setTexture(t.s, t.t); - tm.addVertex(t.x, t.y, t.z); - //android.util.Log.e("rs", "vtx x="+t.x+" y="+t.y+" z="+t.z+" s="+t.s+" t="+t.t); - t.y = .5f; - t.t = 1; - tm.setTexture(t.s, t.t); - tm.addVertex(t.x, t.y, t.z); - //android.util.Log.e("rs", "vtx x="+t.x+" y="+t.y+" z="+t.z+" s="+t.s+" t="+t.t); - - if((runningS*2) > mTriangleOffsetsCount) { - mTriangleOffsets[mTriangleOffsetsCount] = ct*2 * 3; - mTriangleOffsetsTex[mTriangleOffsetsCount] = t.s; - mTriangleOffsetsCount ++; - } - } - - count = (count * 2 - 2); - for (int ct=0; ct < (count-2); ct+= 2) { - tm.addTriangle(ct, ct+1, ct+2); - tm.addTriangle(ct+1, ct+3, ct+2); - } - return tm.create(); - } - - -} - diff --git a/libs/rs/java/Fountain/Android.mk b/libs/rs/java/Fountain/Android.mk index f7e53a8..71944b2 100644 --- a/libs/rs/java/Fountain/Android.mk +++ b/libs/rs/java/Fountain/Android.mk @@ -14,14 +14,18 @@ # limitations under the License. # +ifneq ($(TARGET_SIMULATOR),true) + LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript LOCAL_PACKAGE_NAME := Fountain include $(BUILD_PACKAGE) + +endif diff --git a/libs/rs/java/Fountain/res/drawable/gadgets_clock_mp3.png b/libs/rs/java/Fountain/res/drawable/gadgets_clock_mp3.png Binary files differdeleted file mode 100755 index e91bfb4..0000000 --- a/libs/rs/java/Fountain/res/drawable/gadgets_clock_mp3.png +++ /dev/null diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c deleted file mode 100644 index 73b819b..0000000 --- a/libs/rs/java/Fountain/res/raw/fountain.c +++ /dev/null @@ -1,52 +0,0 @@ -// Fountain test script -#pragma version(1) - -int newPart = 0; - -int main(int launchID) { - int ct; - int count = Control->count; - int rate = Control->rate; - float height = getHeight(); - struct point_s * p = (struct point_s *)point; - - if (rate) { - float rMax = ((float)rate) * 0.005f; - int x = Control->x; - int y = Control->y; - int color = ((int)(Control->r * 255.f)) | - ((int)(Control->g * 255.f)) << 8 | - ((int)(Control->b * 255.f)) << 16 | - (0xf0 << 24); - struct point_s * np = &p[newPart]; - - while (rate--) { - vec2Rand((float *)&np->delta.x, rMax); - np->position.x = x; - np->position.y = y; - np->color = color; - newPart++; - np++; - if (newPart >= count) { - newPart = 0; - np = &p[newPart]; - } - } - } - - for (ct=0; ct < count; ct++) { - float dy = p->delta.y + 0.15f; - float posy = p->position.y + dy; - if ((posy > height) && (dy > 0)) { - dy *= -0.3f; - } - p->delta.y = dy; - p->position.x += p->delta.x; - p->position.y = posy; - p++; - } - - uploadToBufferObject(NAMED_PartBuffer); - drawSimpleMesh(NAMED_PartMesh); - return 1; -} diff --git a/libs/rs/java/Fountain/res/raw/fountain2.rs b/libs/rs/java/Fountain/res/raw/fountain2.rs deleted file mode 100644 index 3301140..0000000 --- a/libs/rs/java/Fountain/res/raw/fountain2.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Fountain test script -#pragma version(1) - -#include "rs_types.rsh" -#include "rs_math.rsh" -#include "rs_graphics.rsh" - -static int newPart = 0; - -typedef struct Control_s { - int x, y; - int rate; - int count; - float r, g, b; - rs_allocation partBuffer; - rs_mesh partMesh; -} Control_t; -Control_t *Control; - -typedef struct Point_s{ - float2 delta; - float2 position; - unsigned int color; -} Point_t; -Point_t *point; - -int main(int launchID) { - int ct; - int count = Control->count; - int rate = Control->rate; - float height = getHeight(); - Point_t * p = point; - - if (rate) { - float rMax = ((float)rate) * 0.005f; - int x = Control->x; - int y = Control->y; - int color = ((int)(Control->r * 255.f)) | - ((int)(Control->g * 255.f)) << 8 | - ((int)(Control->b * 255.f)) << 16 | - (0xf0 << 24); - Point_t * np = &p[newPart]; - - while (rate--) { - np->delta = vec2Rand(rMax); - np->position.x = x; - np->position.y = y; - np->color = color; - newPart++; - np++; - if (newPart >= count) { - newPart = 0; - np = &p[newPart]; - } - } - } - - for (ct=0; ct < count; ct++) { - float dy = p->delta.y + 0.15f; - float posy = p->position.y + dy; - if ((posy > height) && (dy > 0)) { - dy *= -0.3f; - } - p->delta.y = dy; - p->position.x += p->delta.x; - p->position.y = posy; - p++; - } - - uploadToBufferObject(Control->partBuffer); - drawSimpleMesh(Control->partMesh); - return 1; -} diff --git a/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java b/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java index 9ae3e67..116c478 100644 --- a/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java +++ b/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java @@ -67,7 +67,7 @@ public class Fountain extends Activity { // Ideally a game should implement onResume() and onPause() // to take appropriate action when the activity looses focus super.onResume(); - mView.onResume(); + mView.resume(); } @Override @@ -77,7 +77,7 @@ public class Fountain extends Activity { // Ideally a game should implement onResume() and onPause() // to take appropriate action when the activity looses focus super.onPause(); - mView.onPause(); + mView.pause(); diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java index 9356579..be2f9ca 100644 --- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java +++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java @@ -22,94 +22,51 @@ import android.util.Log; public class FountainRS { - public static final int PART_COUNT = 20000; - - static class SomeData { - public int x; - public int y; - public int rate; - public int count; - public float r; - public float g; - public float b; - } + public static final int PART_COUNT = 50000; public FountainRS() { } + private Resources mRes; + private RenderScriptGL mRS; + private ScriptC_fountain mScript; public void init(RenderScriptGL rs, Resources res, int width, int height) { mRS = rs; mRes = res; - initRS(); - } - - public void newTouchPosition(int x, int y, int rate) { - if (mSD.rate == 0) { - mSD.r = ((x & 0x1) != 0) ? 0.f : 1.f; - mSD.g = ((x & 0x2) != 0) ? 0.f : 1.f; - mSD.b = ((x & 0x4) != 0) ? 0.f : 1.f; - if ((mSD.r + mSD.g + mSD.b) < 0.9f) { - mSD.r = 0.8f; - mSD.g = 0.5f; - mSD.b = 1.f; - } - } - mSD.rate = rate; - mSD.x = x; - mSD.y = y; - mIntAlloc.data(mSD); - } - - - ///////////////////////////////////////// - - private Resources mRes; - - private RenderScriptGL mRS; - private Allocation mIntAlloc; - private SimpleMesh mSM; - private SomeData mSD; - private Type mSDType; - private void initRS() { - mSD = new SomeData(); - mSDType = Type.createFromClass(mRS, SomeData.class, 1, "SomeData"); - mIntAlloc = Allocation.createTyped(mRS, mSDType); - mSD.count = PART_COUNT; - mIntAlloc.data(mSD); + ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs); + pfb.setVaryingColor(true); + rs.bindProgramFragment(pfb.create()); - Element.Builder eb = new Element.Builder(mRS); - eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 2), "delta"); - eb.add(Element.createAttrib(mRS, Element.DataType.FLOAT_32, Element.DataKind.POSITION, 2), "position"); - eb.add(Element.createAttrib(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.COLOR, 4), "color"); - Element primElement = eb.create(); + ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);// + // Allocation.USAGE_GRAPHICS_VERTEX); + Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS); + smb.addVertexAllocation(points.getAllocation()); + smb.addIndexSetType(Mesh.Primitive.POINT); + Mesh sm = smb.create(); - SimpleMesh.Builder smb = new SimpleMesh.Builder(mRS); - int vtxSlot = smb.addVertexType(primElement, PART_COUNT); - smb.setPrimitive(Primitive.POINT); - mSM = smb.create(); - mSM.setName("PartMesh"); - - Allocation partAlloc = mSM.createVertexAllocation(vtxSlot); - partAlloc.setName("PartBuffer"); - mSM.bindVertexAllocation(partAlloc, 0); + mScript = new ScriptC_fountain(mRS, mRes, R.raw.fountain); + mScript.set_partMesh(sm); + mScript.bind_point(points); + mRS.bindRootScript(mScript); + } - // All setup of named objects should be done by this point - // because we are about to compile the script. - ScriptC.Builder sb = new ScriptC.Builder(mRS); - sb.setScript(mRes, R.raw.fountain); - sb.setRoot(true); - sb.setType(mSDType, "Control", 0); - sb.setType(mSM.getVertexType(0), "point", 1); - Script script = sb.create(); - script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); + boolean holdingColor[] = new boolean[10]; + public void newTouchPosition(float x, float y, float pressure, int id) { + if (id >= holdingColor.length) { + return; + } + int rate = (int)(pressure * pressure * 500.f); + if (rate > 500) { + rate = 500; + } + if (rate > 0) { + mScript.invoke_addParticles(rate, x, y, id, !holdingColor[id]); + holdingColor[id] = true; + } else { + holdingColor[id] = false; + } - script.bindAllocation(mIntAlloc, 0); - script.bindAllocation(partAlloc, 1); - mRS.contextBindRootScript(script); } - } - - diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java index dfd6a49..69b181d 100644 --- a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java +++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java @@ -52,8 +52,9 @@ public class FountainView extends RSSurfaceView { public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { super.surfaceChanged(holder, format, w, h); if (mRS == null) { - mRS = createRenderScript(false); - mRS.contextSetSurface(w, h, holder.getSurface()); + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); mRender = new FountainRS(); mRender.init(mRS, getResources(), w, h); } @@ -61,9 +62,9 @@ public class FountainView extends RSSurfaceView { @Override protected void onDetachedFromWindow() { - if(mRS != null) { + if (mRS != null) { mRS = null; - destroyRenderScript(); + destroyRenderScriptGL(); } } @@ -71,17 +72,33 @@ public class FountainView extends RSSurfaceView { @Override public boolean onTouchEvent(MotionEvent ev) { - int act = ev.getAction(); + int act = ev.getActionMasked(); if (act == ev.ACTION_UP) { - mRender.newTouchPosition(0, 0, 0); + mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0)); return false; + } else if (act == MotionEvent.ACTION_POINTER_UP) { + // only one pointer going up, we can get the index like this + int pointerIndex = ev.getActionIndex(); + int pointerId = ev.getPointerId(pointerIndex); + mRender.newTouchPosition(0, 0, 0, pointerId); } - float rate = (ev.getPressure() * 50.f); - rate *= rate; - if(rate > 2000.f) { - rate = 2000.f; + int count = ev.getHistorySize(); + int pcount = ev.getPointerCount(); + + for (int p=0; p < pcount; p++) { + int id = ev.getPointerId(p); + mRender.newTouchPosition(ev.getX(p), + ev.getY(p), + ev.getPressure(p), + id); + + for (int i=0; i < count; i++) { + mRender.newTouchPosition(ev.getHistoricalX(p, i), + ev.getHistoricalY(p, i), + ev.getHistoricalPressure(p, i), + id); + } } - mRender.newTouchPosition((int)ev.getX(), (int)ev.getY(), (int)rate); return true; } } diff --git a/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs b/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs new file mode 100644 index 0000000..b8f57a3 --- /dev/null +++ b/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs @@ -0,0 +1,69 @@ +// Fountain test script +#pragma version(1) + +#pragma rs java_package_name(com.android.fountain) + +#pragma stateFragment(parent) + +#include "rs_graphics.rsh" + +static int newPart = 0; +rs_mesh partMesh; + +typedef struct __attribute__((packed, aligned(4))) Point { + float2 delta; + float2 position; + uchar4 color; +} Point_t; +Point_t *point; + +int root() { + float dt = min(rsGetDt(), 0.1f); + rsgClearColor(0.f, 0.f, 0.f, 1.f); + const float height = rsgGetHeight(); + const int size = rsAllocationGetDimX(rsGetAllocation(point)); + float dy2 = dt * (10.f); + Point_t * p = point; + for (int ct=0; ct < size; ct++) { + p->delta.y += dy2; + p->position += p->delta; + if ((p->position.y > height) && (p->delta.y > 0)) { + p->delta.y *= -0.3f; + } + p++; + } + + rsgDrawMesh(partMesh); + return 1; +} + +static float4 partColor[10]; +void addParticles(int rate, float x, float y, int index, bool newColor) +{ + if (newColor) { + partColor[index].x = rsRand(0.5f, 1.0f); + partColor[index].y = rsRand(1.0f); + partColor[index].z = rsRand(1.0f); + } + float rMax = ((float)rate) * 0.02f; + int size = rsAllocationGetDimX(rsGetAllocation(point)); + uchar4 c = rsPackColorTo8888(partColor[index]); + + Point_t * np = &point[newPart]; + float2 p = {x, y}; + while (rate--) { + float angle = rsRand(3.14f * 2.f); + float len = rsRand(rMax); + np->delta.x = len * sin(angle); + np->delta.y = len * cos(angle); + np->position = p; + np->color = c; + newPart++; + np++; + if (newPart >= size) { + newPart = 0; + np = &point[newPart]; + } + } +} + diff --git a/libs/rs/java/ImageProcessing/Android.mk b/libs/rs/java/ImageProcessing/Android.mk index 833427b..7fa30d0 100644 --- a/libs/rs/java/ImageProcessing/Android.mk +++ b/libs/rs/java/ImageProcessing/Android.mk @@ -14,14 +14,19 @@ # limitations under the License. # +ifneq ($(TARGET_SIMULATOR),true) + LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_SRC_FILES := $(call all-java-files-under, src) \ + $(call all-renderscript-files-under, src) #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript LOCAL_PACKAGE_NAME := ImageProcessing include $(BUILD_PACKAGE) + +endif diff --git a/libs/rs/java/ImageProcessing/AndroidManifest.xml b/libs/rs/java/ImageProcessing/AndroidManifest.xml index b48d208..d6a2db4 100644 --- a/libs/rs/java/ImageProcessing/AndroidManifest.xml +++ b/libs/rs/java/ImageProcessing/AndroidManifest.xml @@ -6,7 +6,8 @@ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:label="Image Processing"> - <activity android:name="ImageProcessingActivity"> + <activity android:name="ImageProcessingActivity" + android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> diff --git a/libs/rs/java/ImageProcessing/res/drawable/data.jpg b/libs/rs/java/ImageProcessing/res/drawable/data.jpg Binary files differnew file mode 100644 index 0000000..81a87b1 --- /dev/null +++ b/libs/rs/java/ImageProcessing/res/drawable/data.jpg diff --git a/libs/rs/java/ImageProcessing/res/layout/main.xml b/libs/rs/java/ImageProcessing/res/layout/main.xml index 6770c18..c6ec729 100644 --- a/libs/rs/java/ImageProcessing/res/layout/main.xml +++ b/libs/rs/java/ImageProcessing/res/layout/main.xml @@ -25,9 +25,147 @@ android:id="@+id/display" android:layout_width="320dip" android:layout_height="266dip" /> - + + <Button + android:layout_marginBottom="170dip" + android:layout_width="wrap_content" + android:layout_height="40dip" + android:text="@string/benchmark" + android:onClick="benchmark" + android:layout_gravity="bottom"/> + + <TextView + android:id="@+id/benchmarkText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="100dip" + android:layout_marginBottom="175dip" + android:layout_gravity="bottom" + android:text="@string/saturation"/> + + <SeekBar + android:id="@+id/inSaturation" + android:layout_marginBottom="140dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" /> + + <TextView + android:id="@+id/inSaturationText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="50dip" + android:layout_marginBottom="142dip" + android:textColor="#000" + android:layout_gravity="bottom" + android:text="@string/saturation"/> + + <SeekBar + android:id="@+id/inGamma" + android:layout_marginBottom="110dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" /> + + <TextView + android:id="@+id/inGammaText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="50dip" + android:layout_marginBottom="112dip" + android:textColor="#000" + android:layout_gravity="bottom" + android:text="@string/gamma"/> + <SeekBar - android:id="@+id/threshold" + android:id="@+id/outWhite" + android:layout_marginBottom="80dip" + android:layout_marginLeft="170dip" + android:layout_marginRight="10dip" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" /> + + <TextView + android:id="@+id/outWhiteText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="220dip" + android:layout_marginBottom="82dip" + android:textColor="#000" + android:layout_gravity="bottom" + android:text="@string/out_white"/> + + <SeekBar + android:id="@+id/inWhite" + android:layout_marginBottom="80dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="170dip" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" /> + + <TextView + android:id="@+id/inWhiteText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="50dip" + android:layout_marginBottom="82dip" + android:textColor="#000" + android:layout_gravity="bottom" + android:text="@string/in_white"/> + + <SeekBar + android:id="@+id/outBlack" + android:layout_marginBottom="50dip" + android:layout_marginLeft="170dip" + android:layout_marginRight="10dip" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" /> + + <TextView + android:id="@+id/outBlackText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="220dip" + android:layout_marginBottom="52dip" + android:textColor="#000" + android:layout_gravity="bottom" + android:text="@string/out_black"/> + + <SeekBar + android:id="@+id/inBlack" + android:layout_marginBottom="50dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="170dip" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" /> + + <TextView + android:id="@+id/inBlackText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="50dip" + android:layout_marginBottom="52dip" + android:textColor="#000" + android:layout_gravity="bottom" + android:text="@string/in_black"/> + + <SeekBar + android:id="@+id/radius" android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" @@ -35,4 +173,15 @@ android:layout_height="wrap_content" android:layout_gravity="bottom" /> + <TextView + android:id="@+id/blurText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="50dip" + android:layout_marginBottom="12dip" + android:textColor="#000" + android:layout_gravity="bottom" + android:text="@string/blur_description"/> + </merge>
\ No newline at end of file diff --git a/libs/rs/java/ImageProcessing/res/raw/threshold.rs b/libs/rs/java/ImageProcessing/res/raw/threshold.rs deleted file mode 100644 index 888f0cd..0000000 --- a/libs/rs/java/ImageProcessing/res/raw/threshold.rs +++ /dev/null @@ -1,62 +0,0 @@ -/* -// block of defines matching what RS will insert at runtime. -struct Params_s{ - int inHeight; - int inWidth; - int outHeight; - int outWidth; - float threshold; -}; -struct Params_s * Params; -struct InPixel_s{ - char a; - char b; - char g; - char r; -}; -struct InPixel_s * InPixel; -struct OutPixel_s{ - char a; - char b; - char g; - char r; -}; -struct OutPixel_s * OutPixel; -*/ - -struct color_s { - char b; - char g; - char r; - char a; -}; - -void main() { - int t = uptimeMillis(); - - struct color_s *in = (struct color_s *) InPixel; - struct color_s *out = (struct color_s *) OutPixel; - - int count = Params->inWidth * Params->inHeight; - int i; - float threshold = (Params->threshold * 255.f); - - for (i = 0; i < count; i++) { - float luminance = 0.2125f * in->r + - 0.7154f * in->g + - 0.0721f * in->b; - if (luminance > threshold) { - *out = *in; - } else { - *((int *)out) = *((int *)in) & 0xff000000; - } - - in++; - out++; - } - - t= uptimeMillis() - t; - debugI32("Filter time", t); - - sendToClient(&count, 1, 4, 0); -} diff --git a/libs/rs/java/ImageProcessing/res/values/strings.xml b/libs/rs/java/ImageProcessing/res/values/strings.xml new file mode 100644 index 0000000..cc5cc4d --- /dev/null +++ b/libs/rs/java/ImageProcessing/res/values/strings.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +* Copyright (C) 2008 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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- General --> + <skip /> + <!--slider label --> + <string name="blur_description">Blur Radius</string> + <string name="in_white">In White</string> + <string name="out_white">Out White</string> + <string name="in_black">In Black</string> + <string name="out_black">Out Black</string> + <string name="gamma">Gamma</string> + <string name="saturation">Saturation</string> + <string name="benchmark">Benchmark</string> + +</resources> diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java index 9ce53d8..5de09f7 100644 --- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java @@ -31,53 +31,56 @@ import android.view.SurfaceView; import android.view.SurfaceHolder; import android.widget.ImageView; import android.widget.SeekBar; +import android.widget.TextView; +import android.view.View; import java.lang.Math; -public class ImageProcessingActivity extends Activity implements SurfaceHolder.Callback { - private Bitmap mBitmap; - private Params mParams; - private Script.Invokable mInvokable; - private int[] mInData; - private int[] mOutData; +public class ImageProcessingActivity extends Activity + implements SurfaceHolder.Callback, + SeekBar.OnSeekBarChangeListener { + private Bitmap mBitmapIn; + private Bitmap mBitmapOut; + private Bitmap mBitmapScratch; + private ScriptC_threshold mScript; + private ScriptC_vertical_blur mScriptVBlur; + private ScriptC_horizontal_blur mScriptHBlur; + private int mRadius = 0; + private SeekBar mRadiusSeekBar; + + private float mInBlack = 0.0f; + private SeekBar mInBlackSeekBar; + private float mOutBlack = 0.0f; + private SeekBar mOutBlackSeekBar; + private float mInWhite = 255.0f; + private SeekBar mInWhiteSeekBar; + private float mOutWhite = 255.0f; + private SeekBar mOutWhiteSeekBar; + private float mGamma = 1.0f; + private SeekBar mGammaSeekBar; + + private float mSaturation = 1.0f; + private SeekBar mSaturationSeekBar; + + private TextView mBenchmarkResult; @SuppressWarnings({"FieldCanBeLocal"}) private RenderScript mRS; @SuppressWarnings({"FieldCanBeLocal"}) - private Type mParamsType; - @SuppressWarnings({"FieldCanBeLocal"}) - private Allocation mParamsAllocation; - @SuppressWarnings({"FieldCanBeLocal"}) private Type mPixelType; @SuppressWarnings({"FieldCanBeLocal"}) private Allocation mInPixelsAllocation; @SuppressWarnings({"FieldCanBeLocal"}) private Allocation mOutPixelsAllocation; + @SuppressWarnings({"FieldCanBeLocal"}) + private Allocation mScratchPixelsAllocation1; + private Allocation mScratchPixelsAllocation2; private SurfaceView mSurfaceView; private ImageView mDisplayView; - static class Params { - public int inWidth; - public int outWidth; - public int inHeight; - public int outHeight; - - public float threshold; - } - - static class Pixel { - public byte a; - public byte r; - public byte g; - public byte b; - } - - class FilterCallback extends RenderScript.RSMessage { + class FilterCallback extends RenderScript.RSMessageHandler { private Runnable mAction = new Runnable() { public void run() { - mOutPixelsAllocation.readData(mOutData); - mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0, - mParams.outWidth, mParams.outHeight); mDisplayView.invalidate(); } }; @@ -89,29 +92,212 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C } } - private void javaFilter() { + int in[]; + int interm[]; + int out[]; + int MAX_RADIUS = 25; + // Store our coefficients here + float gaussian[]; + + private long javaFilter() { + final int width = mBitmapIn.getWidth(); + final int height = mBitmapIn.getHeight(); + final int count = width * height; + + if (in == null) { + in = new int[count]; + interm = new int[count]; + out = new int[count]; + gaussian = new float[MAX_RADIUS * 2 + 1]; + mBitmapIn.getPixels(in, 0, width, 0, 0, width, height); + } + long t = java.lang.System.currentTimeMillis(); - int count = mParams.inWidth * mParams.inHeight; - float threshold = mParams.threshold * 255.f; - - for (int i = 0; i < count; i++) { - final float r = (float)((mInData[i] >> 0) & 0xff); - final float g = (float)((mInData[i] >> 8) & 0xff); - final float b = (float)((mInData[i] >> 16) & 0xff); - - final float luminance = 0.2125f * r + - 0.7154f * g + - 0.0721f * b; - if (luminance > threshold) { - mOutData[i] = mInData[i]; - } else { - mOutData[i] = mInData[i] & 0xff000000; + + int w, h, r; + + float fRadius = (float)mRadius; + int radius = (int)mRadius; + + // Compute gaussian weights for the blur + // e is the euler's number + float e = 2.718281828459045f; + float pi = 3.1415926535897932f; + // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 ) + // x is of the form [-radius .. 0 .. radius] + // and sigma varies with radius. + // Based on some experimental radius values and sigma's + // we approximately fit sigma = f(radius) as + // sigma = radius * 0.4 + 0.6 + // The larger the radius gets, the more our gaussian blur + // will resemble a box blur since with large sigma + // the gaussian curve begins to lose its shape + float sigma = 0.4f * fRadius + 0.6f; + // Now compute the coefficints + // We will store some redundant values to save some math during + // the blur calculations + // precompute some values + float coeff1 = 1.0f / (float)(Math.sqrt( 2.0f * pi ) * sigma); + float coeff2 = - 1.0f / (2.0f * sigma * sigma); + float normalizeFactor = 0.0f; + float floatR = 0.0f; + for (r = -radius; r <= radius; r ++) { + floatR = (float)r; + gaussian[r + radius] = coeff1 * (float)Math.pow(e, floatR * floatR * coeff2); + normalizeFactor += gaussian[r + radius]; + } + + //Now we need to normalize the weights because all our coefficients need to add up to one + normalizeFactor = 1.0f / normalizeFactor; + for (r = -radius; r <= radius; r ++) { + floatR = (float)r; + gaussian[r + radius] *= normalizeFactor; + } + + float blurredPixelR = 0.0f; + float blurredPixelG = 0.0f; + float blurredPixelB = 0.0f; + float blurredPixelA = 0.0f; + + for (h = 0; h < height; h ++) { + for (w = 0; w < width; w ++) { + + blurredPixelR = 0.0f; + blurredPixelG = 0.0f; + blurredPixelB = 0.0f; + blurredPixelA = 0.0f; + + for (r = -radius; r <= radius; r ++) { + // Stepping left and right away from the pixel + int validW = w + r; + // Clamp to zero and width max() isn't exposed for ints yet + if (validW < 0) { + validW = 0; + } + if (validW > width - 1) { + validW = width - 1; + } + + int input = in[h*width + validW]; + + int R = ((input >> 24) & 0xff); + int G = ((input >> 16) & 0xff); + int B = ((input >> 8) & 0xff); + int A = (input & 0xff); + + float weight = gaussian[r + radius]; + + blurredPixelR += (float)(R)*weight; + blurredPixelG += (float)(G)*weight; + blurredPixelB += (float)(B)*weight; + blurredPixelA += (float)(A)*weight; + } + + int R = (int)blurredPixelR; + int G = (int)blurredPixelG; + int B = (int)blurredPixelB; + int A = (int)blurredPixelA; + + interm[h*width + w] = (R << 24) | (G << 16) | (B << 8) | (A); + } + } + + for (h = 0; h < height; h ++) { + for (w = 0; w < width; w ++) { + + blurredPixelR = 0.0f; + blurredPixelG = 0.0f; + blurredPixelB = 0.0f; + blurredPixelA = 0.0f; + for (r = -radius; r <= radius; r ++) { + int validH = h + r; + // Clamp to zero and width + if (validH < 0) { + validH = 0; + } + if (validH > height - 1) { + validH = height - 1; + } + + int input = interm[validH*width + w]; + + int R = ((input >> 24) & 0xff); + int G = ((input >> 16) & 0xff); + int B = ((input >> 8) & 0xff); + int A = (input & 0xff); + + float weight = gaussian[r + radius]; + + blurredPixelR += (float)(R)*weight; + blurredPixelG += (float)(G)*weight; + blurredPixelB += (float)(B)*weight; + blurredPixelA += (float)(A)*weight; + } + + int R = (int)blurredPixelR; + int G = (int)blurredPixelG; + int B = (int)blurredPixelB; + int A = (int)blurredPixelA; + + out[h*width + w] = (R << 24) | (G << 16) | (B << 8) | (A); } } t = java.lang.System.currentTimeMillis() - t; + android.util.Log.v("Img", "Java frame time ms " + t); + mBitmapOut.setPixels(out, 0, width, 0, 0, width, height); + return t; + } + + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + + if (seekBar == mRadiusSeekBar) { + float fRadius = progress / 100.0f; + fRadius *= (float)(MAX_RADIUS); + mRadius = (int)fRadius; + + mScript.set_radius(mRadius); + } else if (seekBar == mInBlackSeekBar) { + mInBlack = (float)progress; + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + } else if (seekBar == mOutBlackSeekBar) { + mOutBlack = (float)progress; + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + } else if (seekBar == mInWhiteSeekBar) { + mInWhite = (float)progress + 127.0f; + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + } else if (seekBar == mOutWhiteSeekBar) { + mOutWhite = (float)progress + 127.0f; + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + } else if (seekBar == mGammaSeekBar) { + mGamma = (float)progress/100.0f; + mGamma = Math.max(mGamma, 0.1f); + mGamma = 1.0f / mGamma; + mScriptVBlur.invoke_setGamma(mGamma); + } else if (seekBar == mSaturationSeekBar) { + mSaturation = (float)progress / 50.0f; + mScriptVBlur.invoke_setSaturation(mSaturation); + } + + long t = java.lang.System.currentTimeMillis(); + if (true) { + mScript.invoke_filter(); + mOutPixelsAllocation.copyTo(mBitmapOut); + } else { + javaFilter(); + mDisplayView.invalidate(); + } - android.util.Log.v("Img", "frame time ms " + t); + t = java.lang.System.currentTimeMillis() - t; + android.util.Log.v("Img", "Renderscript frame time core ms " + t); + } + } + + public void onStartTrackingTouch(SeekBar seekBar) { + } + + public void onStopTrackingTouch(SeekBar seekBar) { } @Override @@ -119,45 +305,54 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C super.onCreate(savedInstanceState); setContentView(R.layout.main); - mBitmap = loadBitmap(R.drawable.data); + mBitmapIn = loadBitmap(R.drawable.data); + mBitmapOut = loadBitmap(R.drawable.data); + mBitmapScratch = loadBitmap(R.drawable.data); mSurfaceView = (SurfaceView) findViewById(R.id.surface); mSurfaceView.getHolder().addCallback(this); mDisplayView = (ImageView) findViewById(R.id.display); - mDisplayView.setImageBitmap(mBitmap); - - ((SeekBar) findViewById(R.id.threshold)).setOnSeekBarChangeListener( - new SeekBar.OnSeekBarChangeListener() { - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - mParams.threshold = progress / 100.0f; - mParamsAllocation.data(mParams); - - if (true) { - mInvokable.execute(); - } else { - javaFilter(); - mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0, - mParams.outWidth, mParams.outHeight); - mDisplayView.invalidate(); - } - } - } - - public void onStartTrackingTouch(SeekBar seekBar) { - } - - public void onStopTrackingTouch(SeekBar seekBar) { - } - }); + mDisplayView.setImageBitmap(mBitmapOut); + + mRadiusSeekBar = (SeekBar) findViewById(R.id.radius); + mRadiusSeekBar.setOnSeekBarChangeListener(this); + + mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack); + mInBlackSeekBar.setOnSeekBarChangeListener(this); + mInBlackSeekBar.setMax(128); + mInBlackSeekBar.setProgress(0); + mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack); + mOutBlackSeekBar.setOnSeekBarChangeListener(this); + mOutBlackSeekBar.setMax(128); + mOutBlackSeekBar.setProgress(0); + + mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite); + mInWhiteSeekBar.setOnSeekBarChangeListener(this); + mInWhiteSeekBar.setMax(128); + mInWhiteSeekBar.setProgress(128); + mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite); + mOutWhiteSeekBar.setOnSeekBarChangeListener(this); + mOutWhiteSeekBar.setMax(128); + mOutWhiteSeekBar.setProgress(128); + + mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma); + mGammaSeekBar.setOnSeekBarChangeListener(this); + mGammaSeekBar.setMax(150); + mGammaSeekBar.setProgress(100); + + mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation); + mSaturationSeekBar.setOnSeekBarChangeListener(this); + mSaturationSeekBar.setProgress(50); + + mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText); + mBenchmarkResult.setText("Benchmark not yet run"); } public void surfaceCreated(SurfaceHolder holder) { - mParams = createParams(); - mInvokable = createScript(); - - mInvokable.execute(); + createScript(); + mScript.invoke_filter(); + mOutPixelsAllocation.copyTo(mBitmapOut); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { @@ -166,54 +361,42 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C public void surfaceDestroyed(SurfaceHolder holder) { } - private Script.Invokable createScript() { - mRS = RenderScript.create(); - mRS.mMessageCallback = new FilterCallback(); - - mParamsType = Type.createFromClass(mRS, Params.class, 1, "Parameters"); - mParamsAllocation = Allocation.createTyped(mRS, mParamsType); - mParamsAllocation.data(mParams); - - final int pixelCount = mParams.inWidth * mParams.inHeight; - - mPixelType = Type.createFromClass(mRS, Pixel.class, 1, "Pixel"); - mInPixelsAllocation = Allocation.createSized(mRS, - Element.createUser(mRS, Element.DataType.SIGNED_32), - pixelCount); - mOutPixelsAllocation = Allocation.createSized(mRS, - Element.createUser(mRS, Element.DataType.SIGNED_32), - pixelCount); - - mInData = new int[pixelCount]; - mBitmap.getPixels(mInData, 0, mParams.inWidth, 0, 0, mParams.inWidth, mParams.inHeight); - mInPixelsAllocation.data(mInData); - - mOutData = new int[pixelCount]; - mOutPixelsAllocation.data(mOutData); - - ScriptC.Builder sb = new ScriptC.Builder(mRS); - sb.setType(mParamsType, "Params", 0); - sb.setType(mPixelType, "InPixel", 1); - sb.setType(mPixelType, "OutPixel", 2); - sb.setType(true, 2); - Script.Invokable invokable = sb.addInvokable("main"); - sb.setScript(getResources(), R.raw.threshold); - //sb.setRoot(true); - - ScriptC script = sb.create(); - script.bindAllocation(mParamsAllocation, 0); - script.bindAllocation(mInPixelsAllocation, 1); - script.bindAllocation(mOutPixelsAllocation, 2); - - return invokable; - } - - private Params createParams() { - final Params params = new Params(); - params.inWidth = params.outWidth = mBitmap.getWidth(); - params.inHeight = params.outHeight = mBitmap.getHeight(); - params.threshold = 0.5f; - return params; + private void createScript() { + mRS = RenderScript.create(this); + mRS.setMessageHandler(new FilterCallback()); + + mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn, + Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut, + Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + + Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS)); + tb.setX(mBitmapIn.getWidth()); + tb.setY(mBitmapIn.getHeight()); + mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create()); + mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create()); + + mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur); + mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur); + + mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold); + mScript.set_width(mBitmapIn.getWidth()); + mScript.set_height(mBitmapIn.getHeight()); + mScript.set_radius(mRadius); + + mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); + mScriptVBlur.invoke_setGamma(mGamma); + mScriptVBlur.invoke_setSaturation(mSaturation); + + mScript.bind_InPixel(mInPixelsAllocation); + mScript.bind_OutPixel(mOutPixelsAllocation); + mScript.bind_ScratchPixel1(mScratchPixelsAllocation1); + mScript.bind_ScratchPixel2(mScratchPixelsAllocation2); + + mScript.set_vBlurScript(mScriptVBlur); + mScript.set_hBlurScript(mScriptHBlur); } private Bitmap loadBitmap(int resource) { @@ -229,4 +412,30 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C source.recycle(); return b; } + + // button hook + public void benchmark(View v) { + android.util.Log.v("Img", "Benchmarking"); + int oldRadius = mRadius; + mRadius = MAX_RADIUS; + mScript.set_radius(mRadius); + + long t = java.lang.System.currentTimeMillis(); + + mScript.invoke_filter(); + mOutPixelsAllocation.copyTo(mBitmapOut); + + t = java.lang.System.currentTimeMillis() - t; + android.util.Log.v("Img", "Renderscript frame time core ms " + t); + + //long javaTime = javaFilter(); + //mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms"); + mBenchmarkResult.setText("RS: " + t + " ms"); + + mRadius = oldRadius; + mScript.set_radius(mRadius); + + mScript.invoke_filter(); + mOutPixelsAllocation.copyTo(mBitmapOut); + } } diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs new file mode 100644 index 0000000..652ffd7 --- /dev/null +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs @@ -0,0 +1,30 @@ +#pragma version(1) + +#include "ip.rsh" + +void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) { + float4 *output = (float4 *)v_out; + const FilterStruct *fs = (const FilterStruct *)usrData; + const float4 *input = (const float4 *)rsGetElementAt(fs->ain, 0, y); + + float3 blurredPixel = 0; + const float *gPtr = fs->gaussian; + if ((x > fs->radius) && (x < (fs->width - fs->radius))) { + const float4 *i = input + (x - fs->radius); + for (int r = -fs->radius; r <= fs->radius; r ++) { + blurredPixel += i->xyz * gPtr[0]; + gPtr++; + i++; + } + } else { + for (int r = -fs->radius; r <= fs->radius; r ++) { + // Stepping left and right away from the pixel + int validW = rsClamp(x + r, (uint)0, (uint)(fs->width - 1)); + blurredPixel += input[validW].xyz * gPtr[0]; + gPtr++; + } + } + + output->xyz = blurredPixel; +} + diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ip.rsh b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ip.rsh new file mode 100644 index 0000000..1d7a719 --- /dev/null +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ip.rsh @@ -0,0 +1,15 @@ +#pragma rs java_package_name(com.android.rs.image) + +#define MAX_RADIUS 25 + +typedef struct FilterStruct_s { + rs_allocation ain; + + float *gaussian; //[MAX_RADIUS * 2 + 1]; + int height; + int width; + int radius; + +} FilterStruct; + + diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs new file mode 100644 index 0000000..f2f9a36 --- /dev/null +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs @@ -0,0 +1,93 @@ +#pragma version(1) + +#include "ip.rsh" + +int height; +int width; +int radius; + +uchar4 * InPixel; +uchar4 * OutPixel; +float4 * ScratchPixel1; +float4 * ScratchPixel2; + +rs_script vBlurScript; +rs_script hBlurScript; + +const int CMD_FINISHED = 1; + +// Store our coefficients here +static float gaussian[MAX_RADIUS * 2 + 1]; + + +static void computeGaussianWeights() { + // Compute gaussian weights for the blur + // e is the euler's number + float e = 2.718281828459045f; + float pi = 3.1415926535897932f; + // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 ) + // x is of the form [-radius .. 0 .. radius] + // and sigma varies with radius. + // Based on some experimental radius values and sigma's + // we approximately fit sigma = f(radius) as + // sigma = radius * 0.4 + 0.6 + // The larger the radius gets, the more our gaussian blur + // will resemble a box blur since with large sigma + // the gaussian curve begins to lose its shape + float sigma = 0.4f * (float)radius + 0.6f; + + // Now compute the coefficints + // We will store some redundant values to save some math during + // the blur calculations + // precompute some values + float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma); + float coeff2 = - 1.0f / (2.0f * sigma * sigma); + + float normalizeFactor = 0.0f; + float floatR = 0.0f; + int r; + for (r = -radius; r <= radius; r ++) { + floatR = (float)r; + gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2); + normalizeFactor += gaussian[r + radius]; + } + + //Now we need to normalize the weights because all our coefficients need to add up to one + normalizeFactor = 1.0f / normalizeFactor; + for (r = -radius; r <= radius; r ++) { + floatR = (float)r; + gaussian[r + radius] *= normalizeFactor; + } +} + + +static void copyInput() { + rs_allocation ain; + rsSetObject(&ain,rsGetAllocation(InPixel)); + uint32_t dimx = rsAllocationGetDimX(ain); + uint32_t dimy = rsAllocationGetDimY(ain); + for (uint32_t y = 0; y < dimy; y++) { + for (uint32_t x = 0; x < dimx; x++) { + ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]); + } + } +} + +void filter() { + copyInput(); + computeGaussianWeights(); + + FilterStruct fs; + fs.gaussian = gaussian; + fs.width = width; + fs.height = height; + fs.radius = radius; + + fs.ain = rsGetAllocation(ScratchPixel1); + rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs); + + fs.ain = rsGetAllocation(ScratchPixel2); + rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs); + rsSendToClientBlocking(CMD_FINISHED); +} + diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs new file mode 100644 index 0000000..bd4ae4e --- /dev/null +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs @@ -0,0 +1,93 @@ +#pragma version(1) + +#include "ip.rsh" + +static float inBlack; +static float outBlack; +static float inWhite; +static float outWhite; +static float3 gamma; +static float saturation; + +static float inWMinInB; +static float outWMinOutB; +static float overInWMinInB; +static rs_matrix3x3 colorMat; + +void setLevels(float iBlk, float oBlk, float iWht, float oWht) { + inBlack = iBlk; + outBlack = oBlk; + inWhite = iWht; + outWhite = oWht; + + inWMinInB = inWhite - inBlack; + outWMinOutB = outWhite - outBlack; + overInWMinInB = 1.f / inWMinInB; +} + +void setSaturation(float sat) { + saturation = sat; + + // Saturation + // Linear weights + //float rWeight = 0.3086f; + //float gWeight = 0.6094f; + //float bWeight = 0.0820f; + + // Gamma 2.2 weights (we haven't converted our image to linear space yet for perf reasons) + float rWeight = 0.299f; + float gWeight = 0.587f; + float bWeight = 0.114f; + + float oneMinusS = 1.0f - saturation; + rsMatrixSet(&colorMat, 0, 0, oneMinusS * rWeight + saturation); + rsMatrixSet(&colorMat, 0, 1, oneMinusS * rWeight); + rsMatrixSet(&colorMat, 0, 2, oneMinusS * rWeight); + rsMatrixSet(&colorMat, 1, 0, oneMinusS * gWeight); + rsMatrixSet(&colorMat, 1, 1, oneMinusS * gWeight + saturation); + rsMatrixSet(&colorMat, 1, 2, oneMinusS * gWeight); + rsMatrixSet(&colorMat, 2, 0, oneMinusS * bWeight); + rsMatrixSet(&colorMat, 2, 1, oneMinusS * bWeight); + rsMatrixSet(&colorMat, 2, 2, oneMinusS * bWeight + saturation); +} + +void setGamma(float g) { + gamma = (float3)g; +} + +//sliao +extern uchar3 __attribute__((overloadable)) convert2uchar3(float3 xyz); + +void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) { + uchar4 *output = (uchar4 *)v_out; + const FilterStruct *fs = (const FilterStruct *)usrData; + const float4 *input = (const float4 *)rsGetElementAt(fs->ain, x, 0); + + float3 blurredPixel = 0; + const float *gPtr = fs->gaussian; + if ((y > fs->radius) && (y < (fs->height - fs->radius))) { + const float4 *i = input + ((y - fs->radius) * fs->width); + for (int r = -fs->radius; r <= fs->radius; r ++) { + blurredPixel += i->xyz * gPtr[0]; + gPtr++; + i += fs->width; + } + } else { + for (int r = -fs->radius; r <= fs->radius; r ++) { + int validH = rsClamp(y + r, (uint)0, (uint)(fs->height - 1)); + const float4 *i = input + validH * fs->width; + blurredPixel += i->xyz * gPtr[0]; + gPtr++; + } + } + + float3 temp = rsMatrixMultiply(&colorMat, blurredPixel); + temp = (clamp(temp, 0.f, 255.f) - inBlack) * overInWMinInB; + if (gamma.x != 1.0f) + temp = pow(temp, (float3)gamma); + temp = clamp(temp * outWMinOutB + outBlack, 0.f, 255.f); + + output->xyz = convert_uchar3(temp); + //output->w = input->w; +} + diff --git a/libs/rs/java/ModelViewer/Android.mk b/libs/rs/java/ModelViewer/Android.mk new file mode 100644 index 0000000..efe77d7 --- /dev/null +++ b/libs/rs/java/ModelViewer/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright (C) 2008 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. +# + +ifneq ($(TARGET_SIMULATOR),true) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) +#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript + +LOCAL_PACKAGE_NAME := ModelViewer + +include $(BUILD_PACKAGE) + +endif diff --git a/libs/rs/java/ModelViewer/AndroidManifest.xml b/libs/rs/java/ModelViewer/AndroidManifest.xml new file mode 100644 index 0000000..959fe53 --- /dev/null +++ b/libs/rs/java/ModelViewer/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.modelviewer"> + <application android:label="ModelViewer"> + <activity android:name="SimpleModel" + android:label="SimpleModel" + android:screenOrientation="portrait" + android:theme="@android:style/Theme.Black.NoTitleBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <activity android:name="SceneGraph" + android:label="SceneGraph" + android:theme="@android:style/Theme.Black.NoTitleBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/libs/rs/java/ModelViewer/res/drawable/robot.png b/libs/rs/java/ModelViewer/res/drawable/robot.png Binary files differnew file mode 100644 index 0000000..f7353fd --- /dev/null +++ b/libs/rs/java/ModelViewer/res/drawable/robot.png diff --git a/libs/rs/java/ModelViewer/res/raw/robot.a3d b/libs/rs/java/ModelViewer/res/raw/robot.a3d Binary files differnew file mode 100644 index 0000000..f48895c --- /dev/null +++ b/libs/rs/java/ModelViewer/res/raw/robot.a3d diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraph.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraph.java new file mode 100644 index 0000000..b8717a7 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraph.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.modelviewer; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +public class SceneGraph extends Activity { + + private SceneGraphView mView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new SceneGraphView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mView.resume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mView.pause(); + } + +} + diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java new file mode 100644 index 0000000..f91f31e --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.modelviewer; + +import java.io.Writer; +import java.util.Map; +import java.util.Vector; + +import android.content.res.Resources; +import android.renderscript.*; +import android.renderscript.Element.Builder; +import android.renderscript.Font.Style; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + + +public class SceneGraphRS { + + private final int STATE_LAST_FOCUS = 1; + + int mWidth; + int mHeight; + int mRotation; + + public SceneGraphRS() { + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + mRotation = 0; + initRS(); + } + + private Resources mRes; + private RenderScriptGL mRS; + private Sampler mSampler; + private ProgramStore mPSBackground; + private ProgramFragment mPFBackground; + private ProgramVertex mPVBackground; + private ProgramVertexFixedFunction.Constants mPVA; + + private Allocation mGridImage; + private Allocation mAllocPV; + + private Mesh mMesh; + + private Font mItalic; + private Allocation mTextAlloc; + + private ScriptC_scenegraph mScript; + private ScriptC_transform mTransformScript; + + int mLastX; + int mLastY; + + public void touchEvent(int x, int y) { + int dx = mLastX - x; + if (Math.abs(dx) > 50 || Math.abs(dx) < 3) { + dx = 0; + } + + mRotation -= dx; + if (mRotation > 360) { + mRotation -= 360; + } + if (mRotation < 0) { + mRotation += 360; + } + + mScript.set_gRotate(-(float)mRotation); + + mLastX = x; + mLastY = y; + } + + private void initPFS() { + ProgramStore.Builder b = new ProgramStore.Builder(mRS); + + b.setDepthFunc(ProgramStore.DepthFunc.LESS); + b.setDitherEnabled(false); + b.setDepthMaskEnabled(true); + mPSBackground = b.create(); + + mScript.set_gPFSBackground(mPSBackground); + } + + private void initPF() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMinification(Sampler.Value.LINEAR); + bs.setMagnification(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.CLAMP); + bs.setWrapT(Sampler.Value.CLAMP); + mSampler = bs.create(); + + ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS); + b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, + ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); + mPFBackground = b.create(); + mPFBackground.bindSampler(mSampler, 0); + + mScript.set_gPFBackground(mPFBackground); + } + + private void initPV() { + ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); + mPVBackground = pvb.create(); + + mPVA = new ProgramVertexFixedFunction.Constants(mRS); + ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVA); + + mScript.set_gPVBackground(mPVBackground); + } + + private void loadImage() { + mGridImage = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot, + Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + mScript.set_gTGrid(mGridImage); + } + + private void initTextAllocation() { + String allocString = "Displaying file: R.raw.robot"; + mTextAlloc = Allocation.createFromString(mRS, allocString, Allocation.USAGE_SCRIPT); + mScript.set_gTextAlloc(mTextAlloc); + } + + SgTransform mRootTransform; + SgTransform mGroup1; + + SgTransform mRobot1; + SgTransform mRobot2; + + void initTransformHierarchy() { + mRootTransform = new SgTransform(mRS); + + mGroup1 = new SgTransform(mRS); + mRootTransform.addChild(mGroup1); + + mRobot1 = new SgTransform(mRS); + mRobot2 = new SgTransform(mRS); + + mGroup1.addChild(mRobot1); + mGroup1.addChild(mRobot2); + + mGroup1.setTransform(0, new Float4(0.0f, 0.0f, -15.0f, 0.0f), TransformType.TRANSLATE); + mGroup1.setTransform(1, new Float4(0.0f, 1.0f, 0.0f, 15.0f), TransformType.ROTATE); + + mRobot1.setTransform(0, new Float4(-3.0f, -0.5f, 0.0f, 0.0f), TransformType.TRANSLATE); + mRobot1.setTransform(1, new Float4(0.0f, 1.0f, 0.0f, 20.0f), TransformType.ROTATE); + mRobot1.setTransform(2, new Float4(0.2f, 0.2f, 0.2f, 0.0f), TransformType.SCALE); + + mRobot2.setTransform(0, new Float4(3.0f, 0.0f, 0.0f, 0.0f), TransformType.TRANSLATE); + mRobot2.setTransform(1, new Float4(0.0f, 1.0f, 0.0f, -20.0f), TransformType.ROTATE); + mRobot2.setTransform(2, new Float4(0.3f, 0.3f, 0.3f, 0.0f), TransformType.SCALE); + } + + private void initRS() { + + mScript = new ScriptC_scenegraph(mRS, mRes, R.raw.scenegraph); + mTransformScript = new ScriptC_transform(mRS, mRes, R.raw.transform); + mTransformScript.set_transformScript(mTransformScript); + + mScript.set_gTransformRS(mTransformScript); + + initPFS(); + initPF(); + initPV(); + + loadImage(); + + FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot); + FileA3D.IndexEntry entry = model.getIndexEntry(0); + if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) { + Log.e("rs", "could not load model"); + } else { + mMesh = (Mesh)entry.getObject(); + mScript.set_gTestMesh(mMesh); + } + + mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8); + mScript.set_gItalic(mItalic); + + initTextAllocation(); + + initTransformHierarchy(); + + mScript.bind_gRootNode(mRootTransform.getField()); + + mScript.bind_gGroup(mGroup1.mParent.mChildField); + mScript.bind_gRobot1(mRobot1.mParent.mChildField); + mScript.set_gRobot1Index(mRobot1.mIndexInParentGroup); + mScript.bind_gRobot2(mRobot2.mParent.mChildField); + mScript.set_gRobot2Index(mRobot2.mIndexInParentGroup); + + mRS.bindRootScript(mScript); + } +} + + + diff --git a/libs/rs/java/Film/src/com/android/film/FilmView.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphView.java index 5bc2811..0b6a3b8 100644 --- a/libs/rs/java/Film/src/com/android/film/FilmView.java +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphView.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.film; +package com.android.modelviewer; import java.io.Writer; import java.util.ArrayList; @@ -39,32 +39,34 @@ import android.view.SurfaceView; import android.view.KeyEvent; import android.view.MotionEvent; -public class FilmView extends RSSurfaceView { +public class SceneGraphView extends RSSurfaceView { - public FilmView(Context context) { + public SceneGraphView(Context context) { super(context); //setFocusable(true); } private RenderScriptGL mRS; - private FilmRS mRender; + private SceneGraphRS mRender; public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { super.surfaceChanged(holder, format, w, h); if (mRS == null) { - mRS = createRenderScript(true); - mRS.contextSetSurface(w, h, holder.getSurface()); - mRender = new FilmRS(); + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + sc.setDepth(16, 24); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); + mRender = new SceneGraphRS(); mRender.init(mRS, getResources(), w, h); } } @Override protected void onDetachedFromWindow() { - if(mRS != null) { + if (mRS != null) { mRS = null; - destroyRenderScript(); + destroyRenderScriptGL(); } } @@ -85,7 +87,8 @@ public class FilmView extends RSSurfaceView { if (act == ev.ACTION_UP) { ret = false; } - mRender.setFilmStripPosition((int)ev.getX(), (int)ev.getY() / 5); + + mRender.touchEvent((int)ev.getX(), (int)ev.getY()); return ret; } } diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java new file mode 100644 index 0000000..f5484e2 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.modelviewer; + +import java.io.Writer; +import java.util.Map; +import java.util.Vector; + +import android.content.res.Resources; +import android.renderscript.*; +import android.renderscript.Element.Builder; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + +enum TransformType { + + NONE(0), + TRANSLATE(1), + ROTATE(2), + SCALE(3); + + int mID; + TransformType(int id) { + mID = id; + } +} + +public class SgTransform { + + + ScriptField_SgTransform mTransformField; + ScriptField_SgTransform mChildField; + public ScriptField_SgTransform.Item mTransformData; + + RenderScript mRS; + + Vector mChildren; + SgTransform mParent; + int mIndexInParentGroup; + + public void setParent(SgTransform parent, int parentIndex) { + mParent = parent; + mIndexInParentGroup = parentIndex; + } + + public void addChild(SgTransform child) { + mChildren.add(child); + child.setParent(this, mChildren.size() - 1); + } + + public void setTransform(int index, Float4 value, TransformType type) { + mTransformData.transforms[index] = value; + mTransformData.transformTypes[index] = type.mID; + } + + void initData() { + int numElements = mTransformData.transforms.length; + mTransformData.transformTypes = new int[numElements]; + for (int i = 0; i < numElements; i ++) { + mTransformData.transforms[i] = new Float4(0, 0, 0, 0); + mTransformData.transformTypes[i] = TransformType.NONE.mID; + } + + mTransformData.isDirty = 1; + mTransformData.children = null; + } + + public SgTransform(RenderScript rs) { + mRS = rs; + mTransformData = new ScriptField_SgTransform.Item(); + mChildren = new Vector(); + initData(); + } + + public ScriptField_SgTransform.Item getData() { + if (mChildren.size() != 0) { + mChildField = new ScriptField_SgTransform(mRS, mChildren.size()); + mTransformData.children = mChildField.getAllocation(); + + for (int i = 0; i < mChildren.size(); i ++) { + SgTransform child = (SgTransform)mChildren.get(i); + mChildField.set(child.getData(), i, false); + } + mChildField.copyAll(); + } + + return mTransformData; + } + + public ScriptField_SgTransform getField() { + mTransformField = new ScriptField_SgTransform(mRS, 1); + mTransformField.set(getData(), 0, true); + return mTransformField; + } +} + + + diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java new file mode 100644 index 0000000..9910970 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.modelviewer; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +public class SimpleModel extends Activity { + + private SimpleModelView mView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new SimpleModelView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mView.resume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mView.pause(); + } + +} + diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java new file mode 100644 index 0000000..b18a327 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.modelviewer; + +import java.io.Writer; + +import android.content.res.Resources; +import android.renderscript.*; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + + +public class SimpleModelRS { + + private final int STATE_LAST_FOCUS = 1; + + int mWidth; + int mHeight; + int mRotation; + + public SimpleModelRS() { + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + mRotation = 0; + initRS(); + } + + private Resources mRes; + private RenderScriptGL mRS; + private Sampler mSampler; + private ProgramStore mPSBackground; + private ProgramFragment mPFBackground; + private ProgramVertex mPVBackground; + private ProgramVertexFixedFunction.Constants mPVA; + + private Allocation mGridImage; + private Allocation mAllocPV; + + private Mesh mMesh; + + private Font mItalic; + private Allocation mTextAlloc; + + private ScriptC_simplemodel mScript; + + int mLastX; + int mLastY; + + public void touchEvent(int x, int y) { + int dx = mLastX - x; + if (Math.abs(dx) > 50 || Math.abs(dx) < 3) { + dx = 0; + } + + mRotation -= dx; + if (mRotation > 360) { + mRotation -= 360; + } + if (mRotation < 0) { + mRotation += 360; + } + + mScript.set_gRotate((float)mRotation); + + mLastX = x; + mLastY = y; + } + + private void initPFS() { + ProgramStore.Builder b = new ProgramStore.Builder(mRS); + + b.setDepthFunc(ProgramStore.DepthFunc.LESS); + b.setDitherEnabled(false); + b.setDepthMaskEnabled(true); + mPSBackground = b.create(); + + mScript.set_gPFSBackground(mPSBackground); + } + + private void initPF() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMinification(Sampler.Value.LINEAR); + bs.setMagnification(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.CLAMP); + bs.setWrapT(Sampler.Value.CLAMP); + mSampler = bs.create(); + + ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS); + b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, + ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); + mPFBackground = b.create(); + mPFBackground.bindSampler(mSampler, 0); + + mScript.set_gPFBackground(mPFBackground); + } + + private void initPV() { + ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); + mPVBackground = pvb.create(); + + mPVA = new ProgramVertexFixedFunction.Constants(mRS); + ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVA); + + mScript.set_gPVBackground(mPVBackground); + } + + private void loadImage() { + mGridImage = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot, + Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + mScript.set_gTGrid(mGridImage); + } + + private void initTextAllocation() { + String allocString = "Displaying file: R.raw.robot"; + mTextAlloc = Allocation.createFromString(mRS, allocString, Allocation.USAGE_SCRIPT); + mScript.set_gTextAlloc(mTextAlloc); + } + + private void initRS() { + + mScript = new ScriptC_simplemodel(mRS, mRes, R.raw.simplemodel); + + initPFS(); + initPF(); + initPV(); + + loadImage(); + + FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot); + FileA3D.IndexEntry entry = model.getIndexEntry(0); + if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) { + Log.e("rs", "could not load model"); + } else { + mMesh = (Mesh)entry.getObject(); + mScript.set_gTestMesh(mMesh); + } + + mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8); + mScript.set_gItalic(mItalic); + + initTextAllocation(); + + mRS.bindRootScript(mScript); + } +} + + + diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java new file mode 100644 index 0000000..5c5956d --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.modelviewer; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class SimpleModelView extends RSSurfaceView { + + public SimpleModelView(Context context) { + super(context); + //setFocusable(true); + } + + private RenderScriptGL mRS; + private SimpleModelRS mRender; + + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + sc.setDepth(16, 24); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); + mRender = new SimpleModelRS(); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mRS != null) { + mRS = null; + destroyRenderScriptGL(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + // break point at here + // this method doesn't work when 'extends View' include 'extends ScrollView'. + return super.onKeyDown(keyCode, event); + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) + { + boolean ret = true; + int act = ev.getAction(); + if (act == ev.ACTION_UP) { + ret = false; + } + + mRender.touchEvent((int)ev.getX(), (int)ev.getY()); + return ret; + } +} + + diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs b/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs new file mode 100644 index 0000000..3bee8d6 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs @@ -0,0 +1,91 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.modelviewer) + +#include "rs_graphics.rsh" +#include "transform_def.rsh" + +rs_program_vertex gPVBackground; +rs_program_fragment gPFBackground; + +rs_allocation gTGrid; +rs_mesh gTestMesh; + +rs_program_store gPFSBackground; + +float gRotate; + +rs_font gItalic; +rs_allocation gTextAlloc; + +rs_script gTransformRS; + +SgTransform *gGroup; +SgTransform *gRobot1; +int gRobot1Index; +SgTransform *gRobot2; +int gRobot2Index; + +SgTransform *gRootNode; + +void init() { + gRotate = 0.0f; +} + +int root(int launchID) { + + gGroup->transforms[1].w += 0.5f; + gGroup->isDirty = 1; + + SgTransform *robot1Ptr = gRobot1 + gRobot1Index; + + robot1Ptr->transforms[1].w -= 1.5f; + robot1Ptr->isDirty = 1; + + SgTransform *robot2Ptr = gRobot2 + gRobot2Index; + robot2Ptr->transforms[1].w += 2.5f; + robot2Ptr->isDirty = 1; + + rsForEach(gTransformRS, gRootNode->children, gRootNode->children, 0); + + rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgClearDepth(1.0f); + + rsgBindProgramVertex(gPVBackground); + rs_matrix4x4 proj; + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + rsgBindProgramFragment(gPFBackground); + rsgBindProgramStore(gPFSBackground); + rsgBindTexture(gPFBackground, 0, gTGrid); + + rsgProgramVertexLoadModelMatrix(&robot1Ptr->globalMat); + rsgDrawMesh(gTestMesh); + + rsgProgramVertexLoadModelMatrix(&robot2Ptr->globalMat); + rsgDrawMesh(gTestMesh); + + color(0.3f, 0.3f, 0.3f, 1.0f); + rsgDrawText("Renderscript transform test", 30, 695); + + rsgBindFont(gItalic); + rsgDrawText(gTextAlloc, 30, 730); + + return 10; +} diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/simplemodel.rs b/libs/rs/java/ModelViewer/src/com/android/modelviewer/simplemodel.rs new file mode 100644 index 0000000..419de62 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/simplemodel.rs @@ -0,0 +1,71 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.modelviewer) + +#include "rs_graphics.rsh" + +rs_program_vertex gPVBackground; +rs_program_fragment gPFBackground; + +rs_allocation gTGrid; +rs_mesh gTestMesh; + +rs_program_store gPFSBackground; + +float gRotate; + +rs_font gItalic; +rs_allocation gTextAlloc; + +void init() { + gRotate = 0.0f; +} + +int root(int launchID) { + + rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgClearDepth(1.0f); + + rsgBindProgramVertex(gPVBackground); + rs_matrix4x4 proj; + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + rsgBindProgramFragment(gPFBackground); + rsgBindProgramStore(gPFSBackground); + rsgBindTexture(gPFBackground, 0, gTGrid); + + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + // Position our model on the screen + rsMatrixTranslate(&matrix, 0.0f, -0.3f, -10.0f); + rsMatrixScale(&matrix, 0.2f, 0.2f, 0.2f); + rsMatrixRotate(&matrix, 25.0f, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&matrix, gRotate, 0.0f, 1.0f, 0.0f); + rsgProgramVertexLoadModelMatrix(&matrix); + + rsgDrawMesh(gTestMesh); + + rsgFontColor(0.3f, 0.3f, 0.3f, 1.0f); + rsgDrawText("Renderscript model test", 30, 695); + + rsgBindFont(gItalic); + rsgDrawText(gTextAlloc, 30, 730); + + return 10; +} diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs new file mode 100644 index 0000000..f328025 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs @@ -0,0 +1,96 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.modelviewer) + +#include "transform_def.rsh" + +rs_script transformScript; + +typedef struct { + int changed; + rs_matrix4x4 *mat; +} ParentData; + +static void appendTransformation(int type, float4 data, rs_matrix4x4 *mat) { + rs_matrix4x4 temp; + + switch (type) { + case TRANSFORM_TRANSLATE: + rsMatrixLoadTranslate(&temp, data.x, data.y, data.z); + break; + case TRANSFORM_ROTATE: + rsMatrixLoadRotate(&temp, data.w, data.x, data.y, data.z); + break; + case TRANSFORM_SCALE: + rsMatrixLoadScale(&temp, data.x, data.y, data.z); + break; + } + rsMatrixMultiply(mat, &temp); +} + +void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) { + + SgTransform *data = (SgTransform *)v_out; + const ParentData *parent = (const ParentData *)usrData; + + //rsDebug("Transform data", (int)data); + //rsDebug("Entering parent", (int)parent); + + rs_matrix4x4 *localMat = &data->localMat; + rs_matrix4x4 *globalMat = &data->globalMat; + + ParentData toChild; + toChild.changed = 0; + toChild.mat = globalMat; + + //rsDebug("Transform is dirty", data->isDirty); + + // Refresh matrices if dirty + if (data->isDirty) { + data->isDirty = 0; + toChild.changed = 1; + + // Reset our local matrix + rsMatrixLoadIdentity(localMat); + + for (int i = 0; i < 16; i ++) { + if (data->transformTypes[i] == TRANSFORM_NONE) { + break; + } + //rsDebug("Transform adding transformation", transformTypes[i]); + appendTransformation(data->transformTypes[i], data->transforms[i], localMat); + } + } + + //rsDebug("Transform checking parent", (int)0); + + if (parent) { + if (parent->changed) { + toChild.changed = 1; + + rsMatrixLoad(globalMat, parent->mat); + rsMatrixMultiply(globalMat, localMat); + } + } else { + rsMatrixLoad(globalMat, localMat); + } + + //rsDebug("Transform calling self with child ", (int)data->children.p); + if (data->children.p) { + rsForEach(transformScript, data->children, data->children, (void*)&toChild); + } +} diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh new file mode 100644 index 0000000..24a36c1 --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh @@ -0,0 +1,35 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.modelviewer) + +#define TRANSFORM_NONE 0 +#define TRANSFORM_TRANSLATE 1 +#define TRANSFORM_ROTATE 2 +#define TRANSFORM_SCALE 3 + +typedef struct __attribute__((packed, aligned(4))) SgTransform { + rs_matrix4x4 globalMat; + rs_matrix4x4 localMat; + + float4 transforms[16]; + int transformTypes[16]; + + int isDirty; + + rs_allocation children; + +} SgTransform; diff --git a/libs/rs/java/Samples/Android.mk b/libs/rs/java/Samples/Android.mk new file mode 100644 index 0000000..65ae734 --- /dev/null +++ b/libs/rs/java/Samples/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright (C) 2008 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. +# + +ifneq ($(TARGET_SIMULATOR),true) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) +#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript + +LOCAL_PACKAGE_NAME := Samples + +include $(BUILD_PACKAGE) + +endif diff --git a/libs/rs/java/Samples/AndroidManifest.xml b/libs/rs/java/Samples/AndroidManifest.xml new file mode 100644 index 0000000..9646a77 --- /dev/null +++ b/libs/rs/java/Samples/AndroidManifest.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.samples"> + <application android:label="Samples" + android:icon="@drawable/test_pattern"> + <activity android:name="RsList" + android:label="RsList" + android:theme="@android:style/Theme.Black.NoTitleBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="RsRenderStates" + android:label="RsStates" + android:theme="@android:style/Theme.Black.NoTitleBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="RsBench" + android:label="RsBenchmark" + android:theme="@android:style/Theme.Black.NoTitleBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/libs/rs/java/Samples/res/drawable/checker.png b/libs/rs/java/Samples/res/drawable/checker.png Binary files differnew file mode 100644 index 0000000..b631e1e --- /dev/null +++ b/libs/rs/java/Samples/res/drawable/checker.png diff --git a/libs/rs/java/Samples/res/drawable/cubemap_test.png b/libs/rs/java/Samples/res/drawable/cubemap_test.png Binary files differnew file mode 100644 index 0000000..baf35d0 --- /dev/null +++ b/libs/rs/java/Samples/res/drawable/cubemap_test.png diff --git a/libs/rs/java/Samples/res/drawable/data.png b/libs/rs/java/Samples/res/drawable/data.png Binary files differnew file mode 100644 index 0000000..8e34714 --- /dev/null +++ b/libs/rs/java/Samples/res/drawable/data.png diff --git a/libs/rs/java/Samples/res/drawable/leaf.png b/libs/rs/java/Samples/res/drawable/leaf.png Binary files differnew file mode 100644 index 0000000..3cd3775 --- /dev/null +++ b/libs/rs/java/Samples/res/drawable/leaf.png diff --git a/libs/rs/java/Samples/res/drawable/test_pattern.png b/libs/rs/java/Samples/res/drawable/test_pattern.png Binary files differnew file mode 100644 index 0000000..e7d1455 --- /dev/null +++ b/libs/rs/java/Samples/res/drawable/test_pattern.png diff --git a/libs/rs/java/Samples/res/drawable/torusmap.png b/libs/rs/java/Samples/res/drawable/torusmap.png Binary files differnew file mode 100644 index 0000000..1e08f3b --- /dev/null +++ b/libs/rs/java/Samples/res/drawable/torusmap.png diff --git a/libs/rs/java/Samples/res/raw/multitexf.glsl b/libs/rs/java/Samples/res/raw/multitexf.glsl new file mode 100644 index 0000000..e492a47 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/multitexf.glsl @@ -0,0 +1,13 @@ +varying vec2 varTex0; + +void main() { + vec2 t0 = varTex0.xy; + lowp vec4 col0 = texture2D(UNI_Tex0, t0).rgba; + lowp vec4 col1 = texture2D(UNI_Tex1, t0*4.0).rgba; + lowp vec4 col2 = texture2D(UNI_Tex2, t0).rgba; + col0.xyz = col0.xyz*col1.xyz*1.5; + col0.xyz = mix(col0.xyz, col2.xyz, col2.w); + col0.w = 0.5; + gl_FragColor = col0; +} + diff --git a/libs/rs/java/Samples/res/raw/shader2f.glsl b/libs/rs/java/Samples/res/raw/shader2f.glsl new file mode 100644 index 0000000..5fc05f1 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shader2f.glsl @@ -0,0 +1,29 @@ +varying vec3 varWorldPos; +varying vec3 varWorldNormal; +varying vec2 varTex0; + +void main() { + + vec3 V = normalize(-varWorldPos.xyz); + vec3 worldNorm = normalize(varWorldNormal); + + vec3 light0Vec = normalize(UNI_light0_Posision.xyz - varWorldPos); + vec3 light0R = -reflect(light0Vec, worldNorm); + float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light0_Diffuse; + float light0Spec = clamp(dot(light0R, V), 0.001, 1.0); + float light0_Specular = pow(light0Spec, UNI_light0_CosinePower) * UNI_light0_Specular; + + vec3 light1Vec = normalize(UNI_light1_Posision.xyz - varWorldPos); + vec3 light1R = reflect(light1Vec, worldNorm); + float light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light1_Diffuse; + float light1Spec = clamp(dot(light1R, V), 0.001, 1.0); + float light1_Specular = pow(light1Spec, UNI_light1_CosinePower) * UNI_light1_Specular; + + vec2 t0 = varTex0.xy; + lowp vec4 col = texture2D(UNI_Tex0, t0).rgba; + col.xyz = col.xyz * (light0_Diffuse * UNI_light0_DiffuseColor.xyz + light1_Diffuse * UNI_light1_DiffuseColor.xyz); + col.xyz += light0_Specular * UNI_light0_SpecularColor.xyz; + col.xyz += light1_Specular * UNI_light1_SpecularColor.xyz; + gl_FragColor = col; +} + diff --git a/libs/rs/java/Samples/res/raw/shader2movev.glsl b/libs/rs/java/Samples/res/raw/shader2movev.glsl new file mode 100644 index 0000000..a2c807e --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shader2movev.glsl @@ -0,0 +1,21 @@ +varying vec3 varWorldPos; +varying vec3 varWorldNormal; +varying vec2 varTex0; + +// This is where actual shader code begins +void main() { + vec4 objPos = ATTRIB_position; + vec3 oldPos = objPos.xyz; + objPos.xyz += 0.1*sin(objPos.xyz*2.0 + UNI_time); + objPos.xyz += 0.05*sin(objPos.xyz*4.0 + UNI_time*0.5); + objPos.xyz += 0.02*sin(objPos.xyz*7.0 + UNI_time*0.75); + vec4 worldPos = UNI_model * objPos; + gl_Position = UNI_proj * worldPos; + + mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); + vec3 worldNorm = model3 * (ATTRIB_normal + oldPos - objPos.xyz); + + varWorldPos = worldPos.xyz; + varWorldNormal = worldNorm; + varTex0 = ATTRIB_texture0; +} diff --git a/libs/rs/java/Samples/res/raw/shader2v.glsl b/libs/rs/java/Samples/res/raw/shader2v.glsl new file mode 100644 index 0000000..e6885a3 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shader2v.glsl @@ -0,0 +1,17 @@ +varying vec3 varWorldPos; +varying vec3 varWorldNormal; +varying vec2 varTex0; + +// This is where actual shader code begins +void main() { + vec4 objPos = ATTRIB_position; + vec4 worldPos = UNI_model * objPos; + gl_Position = UNI_proj * worldPos; + + mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); + vec3 worldNorm = model3 * ATTRIB_normal; + + varWorldPos = worldPos.xyz; + varWorldNormal = worldNorm; + varTex0 = ATTRIB_texture0; +} diff --git a/libs/rs/java/Samples/res/raw/shaderarrayf.glsl b/libs/rs/java/Samples/res/raw/shaderarrayf.glsl new file mode 100644 index 0000000..238ecad --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shaderarrayf.glsl @@ -0,0 +1,16 @@ + +varying lowp float light0_Diffuse; +varying lowp float light0_Specular; +varying lowp float light1_Diffuse; +varying lowp float light1_Specular; +varying vec2 varTex0; + +void main() { + vec2 t0 = varTex0.xy; + lowp vec4 col = texture2D(UNI_Tex0, t0).rgba; + col.xyz = col.xyz * (light0_Diffuse * UNI_light_DiffuseColor[0].xyz + light1_Diffuse * UNI_light_DiffuseColor[1].xyz); + col.xyz += light0_Specular * UNI_light_SpecularColor[0].xyz; + col.xyz += light1_Specular * UNI_light_SpecularColor[1].xyz; + gl_FragColor = col; +} + diff --git a/libs/rs/java/Samples/res/raw/shaderarrayv.glsl b/libs/rs/java/Samples/res/raw/shaderarrayv.glsl new file mode 100644 index 0000000..7a1310a --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shaderarrayv.glsl @@ -0,0 +1,32 @@ +varying float light0_Diffuse; +varying float light0_Specular; +varying float light1_Diffuse; +varying float light1_Specular; +varying vec2 varTex0; + +// This is where actual shader code begins +void main() { + vec4 worldPos = UNI_model[0] * ATTRIB_position; + worldPos = UNI_model[1] * worldPos; + gl_Position = UNI_proj * worldPos; + + mat4 model0 = UNI_model[0]; + mat3 model3 = mat3(model0[0].xyz, model0[1].xyz, model0[2].xyz); + vec3 worldNorm = model3 * ATTRIB_normal; + vec3 V = normalize(-worldPos.xyz); + + vec3 light0Vec = normalize(UNI_light_Posision[0].xyz - worldPos.xyz); + vec3 light0R = -reflect(light0Vec, worldNorm); + light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light_Diffuse[0]; + float light0Spec = clamp(dot(light0R, V), 0.001, 1.0); + light0_Specular = pow(light0Spec, UNI_light_CosinePower[0]) * UNI_light_Specular[0]; + + vec3 light1Vec = normalize(UNI_light_Posision[1].xyz - worldPos.xyz); + vec3 light1R = reflect(light1Vec, worldNorm); + light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light_Diffuse[1]; + float light1Spec = clamp(dot(light1R, V), 0.001, 1.0); + light1_Specular = pow(light1Spec, UNI_light_CosinePower[1]) * UNI_light_Specular[1]; + + gl_PointSize = 1.0; + varTex0 = ATTRIB_texture0; +} diff --git a/libs/rs/java/Samples/res/raw/shadercubef.glsl b/libs/rs/java/Samples/res/raw/shadercubef.glsl new file mode 100644 index 0000000..15696a4 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shadercubef.glsl @@ -0,0 +1,8 @@ + +varying vec3 worldNormal; + +void main() { + lowp vec4 col = textureCube(UNI_Tex0, worldNormal); + gl_FragColor = col; +} + diff --git a/libs/rs/java/Samples/res/raw/shadercubev.glsl b/libs/rs/java/Samples/res/raw/shadercubev.glsl new file mode 100644 index 0000000..70f5cd6 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shadercubev.glsl @@ -0,0 +1,10 @@ +varying vec3 worldNormal; + +// This is where actual shader code begins +void main() { + vec4 worldPos = UNI_model * ATTRIB_position; + gl_Position = UNI_proj * worldPos; + + mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); + worldNormal = model3 * ATTRIB_normal; +} diff --git a/libs/rs/java/Samples/res/raw/shaderf.glsl b/libs/rs/java/Samples/res/raw/shaderf.glsl new file mode 100644 index 0000000..d56e203 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shaderf.glsl @@ -0,0 +1,16 @@ + +varying lowp float light0_Diffuse; +varying lowp float light0_Specular; +varying lowp float light1_Diffuse; +varying lowp float light1_Specular; +varying vec2 varTex0; + +void main() { + vec2 t0 = varTex0.xy; + lowp vec4 col = texture2D(UNI_Tex0, t0).rgba; + col.xyz = col.xyz * (light0_Diffuse * UNI_light0_DiffuseColor.xyz + light1_Diffuse * UNI_light1_DiffuseColor.xyz); + col.xyz += light0_Specular * UNI_light0_SpecularColor.xyz; + col.xyz += light1_Specular * UNI_light1_SpecularColor.xyz; + gl_FragColor = col; +} + diff --git a/libs/rs/java/Samples/res/raw/shaderv.glsl b/libs/rs/java/Samples/res/raw/shaderv.glsl new file mode 100644 index 0000000..f7d01de --- /dev/null +++ b/libs/rs/java/Samples/res/raw/shaderv.glsl @@ -0,0 +1,30 @@ +varying float light0_Diffuse; +varying float light0_Specular; +varying float light1_Diffuse; +varying float light1_Specular; +varying vec2 varTex0; + +// This is where actual shader code begins +void main() { + vec4 worldPos = UNI_model * ATTRIB_position; + gl_Position = UNI_proj * worldPos; + + mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); + vec3 worldNorm = model3 * ATTRIB_normal; + vec3 V = normalize(-worldPos.xyz); + + vec3 light0Vec = normalize(UNI_light0_Posision.xyz - worldPos.xyz); + vec3 light0R = -reflect(light0Vec, worldNorm); + light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light0_Diffuse; + float light0Spec = clamp(dot(light0R, V), 0.001, 1.0); + light0_Specular = pow(light0Spec, UNI_light0_CosinePower) * UNI_light0_Specular; + + vec3 light1Vec = normalize(UNI_light1_Posision.xyz - worldPos.xyz); + vec3 light1R = reflect(light1Vec, worldNorm); + light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light1_Diffuse; + float light1Spec = clamp(dot(light1R, V), 0.001, 1.0); + light1_Specular = pow(light1Spec, UNI_light1_CosinePower) * UNI_light1_Specular; + + gl_PointSize = 1.0; + varTex0 = ATTRIB_texture0; +} diff --git a/libs/rs/java/Samples/res/raw/torus.a3d b/libs/rs/java/Samples/res/raw/torus.a3d Binary files differnew file mode 100644 index 0000000..0322b01 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/torus.a3d diff --git a/libs/rs/java/Samples/src/com/android/samples/RsBench.java b/libs/rs/java/Samples/src/com/android/samples/RsBench.java new file mode 100644 index 0000000..a29dddc --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsBench.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +public class RsBench extends Activity { + + private RsBenchView mView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new RsBenchView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity loses focus + super.onResume(); + mView.resume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity loses focus + super.onPause(); + mView.pause(); + } + +} + diff --git a/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java b/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java new file mode 100644 index 0000000..1afcee3 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import java.io.Writer; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.renderscript.*; +import android.renderscript.Allocation.MipmapControl; +import android.renderscript.Program.TextureType; +import android.renderscript.ProgramStore.DepthFunc; +import android.renderscript.ProgramStore.BlendSrcFunc; +import android.renderscript.ProgramStore.BlendDstFunc; +import android.renderscript.Sampler.Value; +import android.util.Log; + + +public class RsBenchRS { + + int mWidth; + int mHeight; + + public RsBenchRS() { + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + mOptionsARGB.inScaled = false; + mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888; + mMode = 0; + mMaxModes = 0; + initRS(); + } + + private Resources mRes; + private RenderScriptGL mRS; + + private Sampler mLinearClamp; + private Sampler mLinearWrap; + private Sampler mMipLinearWrap; + private Sampler mNearestClamp; + private Sampler mMipLinearAniso8; + private Sampler mMipLinearAniso15; + + private ProgramStore mProgStoreBlendNoneDepth; + private ProgramStore mProgStoreBlendNone; + private ProgramStore mProgStoreBlendAlpha; + private ProgramStore mProgStoreBlendAdd; + + private ProgramFragment mProgFragmentTexture; + private ProgramFragment mProgFragmentColor; + + private ProgramVertex mProgVertex; + private ProgramVertexFixedFunction.Constants mPVA; + + // Custom shaders + private ProgramVertex mProgVertexCustom; + private ProgramFragment mProgFragmentCustom; + private ProgramFragment mProgFragmentMultitex; + private ProgramVertex mProgVertexPixelLight; + private ProgramVertex mProgVertexPixelLightMove; + private ProgramFragment mProgFragmentPixelLight; + private ScriptField_VertexShaderConstants_s mVSConst; + private ScriptField_FragentShaderConstants_s mFSConst; + private ScriptField_VertexShaderConstants3_s mVSConstPixel; + private ScriptField_FragentShaderConstants3_s mFSConstPixel; + + private ProgramVertex mProgVertexCube; + private ProgramFragment mProgFragmentCube; + + private ProgramRaster mCullBack; + private ProgramRaster mCullFront; + private ProgramRaster mCullNone; + + private Allocation mTexTorus; + private Allocation mTexOpaque; + private Allocation mTexTransparent; + private Allocation mTexChecker; + private Allocation mTexCube; + + private Mesh m10by10Mesh; + private Mesh m100by100Mesh; + private Mesh mWbyHMesh; + private Mesh mTorus; + + Font mFontSans; + Font mFontSerif; + Font mFontSerifBold; + Font mFontSerifItalic; + Font mFontSerifBoldItalic; + Font mFontMono; + private Allocation mTextAlloc; + + private ScriptC_rsbench mScript; + + private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options(); + + int mMode; + int mMaxModes; + + public void onActionDown(int x, int y) { + mMode ++; + mMode = mMode % mMaxModes; + mScript.set_gDisplayMode(mMode); + } + + ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) { + ProgramStore.Builder builder = new ProgramStore.Builder(rs); + builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); + builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE); + builder.setDitherEnabled(false); + builder.setDepthMaskEnabled(false); + return builder.create(); + } + + private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) { + + Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS, + 2, Mesh.TriangleMeshBuilder.TEXTURE_0); + + for (int y = 0; y <= hResolution; y++) { + final float normalizedY = (float)y / hResolution; + final float yOffset = (normalizedY - 0.5f) * height; + for (int x = 0; x <= wResolution; x++) { + float normalizedX = (float)x / wResolution; + float xOffset = (normalizedX - 0.5f) * width; + tmb.setTexture((float)x % 2, (float)y % 2); + tmb.addVertex(xOffset, yOffset); + } + } + + for (int y = 0; y < hResolution; y++) { + final int curY = y * (wResolution + 1); + final int belowY = (y + 1) * (wResolution + 1); + for (int x = 0; x < wResolution; x++) { + int curV = curY + x; + int belowV = belowY + x; + tmb.addTriangle(curV, belowV, curV + 1); + tmb.addTriangle(belowV, belowV + 1, curV + 1); + } + } + + return tmb.create(true); + } + + private void initProgramStore() { + // Use stock the stock program store object + mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS); + mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS); + + // Create a custom program store + ProgramStore.Builder builder = new ProgramStore.Builder(mRS); + builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); + builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA, + ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA); + builder.setDitherEnabled(false); + builder.setDepthMaskEnabled(false); + mProgStoreBlendAlpha = builder.create(); + + mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS); + + mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth); + mScript.set_gProgStoreBlendNone(mProgStoreBlendNone); + mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha); + mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd); + } + + private void initProgramFragment() { + + ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS); + texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, + ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); + mProgFragmentTexture = texBuilder.create(); + mProgFragmentTexture.bindSampler(mLinearClamp, 0); + + ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS); + colBuilder.setVaryingColor(false); + mProgFragmentColor = colBuilder.create(); + + mScript.set_gProgFragmentColor(mProgFragmentColor); + mScript.set_gProgFragmentTexture(mProgFragmentTexture); + } + + private void initProgramVertex() { + ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); + mProgVertex = pvb.create(); + + mPVA = new ProgramVertexFixedFunction.Constants(mRS); + ((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA); + Matrix4f proj = new Matrix4f(); + proj.loadOrthoWindow(mWidth, mHeight); + mPVA.setProjection(proj); + + mScript.set_gProgVertex(mProgVertex); + } + + private void initCustomShaders() { + mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1); + mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1); + mScript.bind_gVSConstants(mVSConst); + mScript.bind_gFSConstants(mFSConst); + + mVSConstPixel = new ScriptField_VertexShaderConstants3_s(mRS, 1); + mFSConstPixel = new ScriptField_FragentShaderConstants3_s(mRS, 1); + mScript.bind_gVSConstPixel(mVSConstPixel); + mScript.bind_gFSConstPixel(mFSConstPixel); + + // Initialize the shader builder + ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS); + // Specify the resource that contains the shader string + pvbCustom.setShader(mRes, R.raw.shaderv); + // Use a script field to specify the input layout + pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + // Define the constant input layout + pvbCustom.addConstant(mVSConst.getAllocation().getType()); + mProgVertexCustom = pvbCustom.create(); + // Bind the source of constant data + mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0); + + ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS); + // Specify the resource that contains the shader string + pfbCustom.setShader(mRes, R.raw.shaderf); + // Tell the builder how many textures we have + pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); + // Define the constant input layout + pfbCustom.addConstant(mFSConst.getAllocation().getType()); + mProgFragmentCustom = pfbCustom.create(); + // Bind the source of constant data + mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0); + + // Cubemap test shaders + pvbCustom = new ProgramVertex.Builder(mRS); + pvbCustom.setShader(mRes, R.raw.shadercubev); + pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + pvbCustom.addConstant(mVSConst.getAllocation().getType()); + mProgVertexCube = pvbCustom.create(); + mProgVertexCube.bindConstants(mVSConst.getAllocation(), 0); + + pfbCustom = new ProgramFragment.Builder(mRS); + pfbCustom.setShader(mRes, R.raw.shadercubef); + pfbCustom.addTexture(Program.TextureType.TEXTURE_CUBE); + mProgFragmentCube = pfbCustom.create(); + + pvbCustom = new ProgramVertex.Builder(mRS); + pvbCustom.setShader(mRes, R.raw.shader2v); + pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + pvbCustom.addConstant(mVSConstPixel.getAllocation().getType()); + mProgVertexPixelLight = pvbCustom.create(); + mProgVertexPixelLight.bindConstants(mVSConstPixel.getAllocation(), 0); + + pvbCustom = new ProgramVertex.Builder(mRS); + pvbCustom.setShader(mRes, R.raw.shader2movev); + pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + pvbCustom.addConstant(mVSConstPixel.getAllocation().getType()); + mProgVertexPixelLightMove = pvbCustom.create(); + mProgVertexPixelLightMove.bindConstants(mVSConstPixel.getAllocation(), 0); + + pfbCustom = new ProgramFragment.Builder(mRS); + pfbCustom.setShader(mRes, R.raw.shader2f); + pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); + pfbCustom.addConstant(mFSConstPixel.getAllocation().getType()); + mProgFragmentPixelLight = pfbCustom.create(); + mProgFragmentPixelLight.bindConstants(mFSConstPixel.getAllocation(), 0); + + pfbCustom = new ProgramFragment.Builder(mRS); + pfbCustom.setShader(mRes, R.raw.multitexf); + for (int texCount = 0; texCount < 3; texCount ++) { + pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); + } + mProgFragmentMultitex = pfbCustom.create(); + + mScript.set_gProgVertexCustom(mProgVertexCustom); + mScript.set_gProgFragmentCustom(mProgFragmentCustom); + mScript.set_gProgVertexCube(mProgVertexCube); + mScript.set_gProgFragmentCube(mProgFragmentCube); + mScript.set_gProgVertexPixelLight(mProgVertexPixelLight); + mScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove); + mScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight); + mScript.set_gProgFragmentMultitex(mProgFragmentMultitex); + } + + private Allocation loadTextureRGB(int id) { + return Allocation.createFromBitmapResource(mRS, mRes, id, + Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + } + + private Allocation loadTextureARGB(int id) { + Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB); + return Allocation.createFromBitmap(mRS, b, + Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + } + + private void loadImages() { + mTexTorus = loadTextureRGB(R.drawable.torusmap); + mTexOpaque = loadTextureRGB(R.drawable.data); + mTexTransparent = loadTextureARGB(R.drawable.leaf); + mTexChecker = loadTextureRGB(R.drawable.checker); + Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test); + mTexCube = Allocation.createCubemapFromBitmap(mRS, b); + + mScript.set_gTexTorus(mTexTorus); + mScript.set_gTexOpaque(mTexOpaque); + mScript.set_gTexTransparent(mTexTransparent); + mScript.set_gTexChecker(mTexChecker); + mScript.set_gTexCube(mTexCube); + } + + private void initFonts() { + // Sans font by family name + mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8); + mFontSerif = Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8); + // Create fonts by family and style + mFontSerifBold = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8); + mFontSerifItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8); + mFontSerifBoldItalic = Font.create(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8); + mFontMono = Font.create(mRS, mRes, "mono", Font.Style.NORMAL, 8); + + mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT); + + mScript.set_gFontSans(mFontSans); + mScript.set_gFontSerif(mFontSerif); + mScript.set_gFontSerifBold(mFontSerifBold); + mScript.set_gFontSerifItalic(mFontSerifItalic); + mScript.set_gFontSerifBoldItalic(mFontSerifBoldItalic); + mScript.set_gFontMono(mFontMono); + mScript.set_gTextAlloc(mTextAlloc); + } + + private void initMesh() { + m10by10Mesh = getMbyNMesh(mWidth, mHeight, 10, 10); + mScript.set_g10by10Mesh(m10by10Mesh); + m100by100Mesh = getMbyNMesh(mWidth, mHeight, 100, 100); + mScript.set_g100by100Mesh(m100by100Mesh); + mWbyHMesh= getMbyNMesh(mWidth, mHeight, mWidth/4, mHeight/4); + mScript.set_gWbyHMesh(mWbyHMesh); + + FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus); + FileA3D.IndexEntry entry = model.getIndexEntry(0); + if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) { + Log.e("rs", "could not load model"); + } else { + mTorus = (Mesh)entry.getObject(); + mScript.set_gTorusMesh(mTorus); + } + } + + private void initSamplers() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMinification(Sampler.Value.LINEAR); + bs.setMagnification(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.WRAP); + bs.setWrapT(Sampler.Value.WRAP); + mLinearWrap = bs.create(); + + mLinearClamp = Sampler.CLAMP_LINEAR(mRS); + mNearestClamp = Sampler.CLAMP_NEAREST(mRS); + mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS); + + bs = new Sampler.Builder(mRS); + bs.setMinification(Sampler.Value.LINEAR_MIP_LINEAR); + bs.setMagnification(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.WRAP); + bs.setWrapT(Sampler.Value.WRAP); + bs.setAnisotropy(8.0f); + mMipLinearAniso8 = bs.create(); + bs.setAnisotropy(15.0f); + mMipLinearAniso15 = bs.create(); + + mScript.set_gLinearClamp(mLinearClamp); + mScript.set_gLinearWrap(mLinearWrap); + mScript.set_gMipLinearWrap(mMipLinearWrap); + mScript.set_gMipLinearAniso8(mMipLinearAniso8); + mScript.set_gMipLinearAniso15(mMipLinearAniso15); + mScript.set_gNearestClamp(mNearestClamp); + } + + private void initProgramRaster() { + mCullBack = ProgramRaster.CULL_BACK(mRS); + mCullFront = ProgramRaster.CULL_FRONT(mRS); + mCullNone = ProgramRaster.CULL_NONE(mRS); + + mScript.set_gCullBack(mCullBack); + mScript.set_gCullFront(mCullFront); + mScript.set_gCullNone(mCullNone); + } + + private void initRS() { + + mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench); + + mMaxModes = mScript.get_gMaxModes(); + + initSamplers(); + initProgramStore(); + initProgramFragment(); + initProgramVertex(); + initFonts(); + loadImages(); + initMesh(); + initProgramRaster(); + initCustomShaders(); + + mRS.bindRootScript(mScript); + } +} + + + diff --git a/libs/rs/java/Samples/src/com/android/samples/RsBenchView.java b/libs/rs/java/Samples/src/com/android/samples/RsBenchView.java new file mode 100644 index 0000000..0a56668 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsBenchView.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class RsBenchView extends RSSurfaceView { + + public RsBenchView(Context context) { + super(context); + } + + private RenderScriptGL mRS; + private RsBenchRS mRender; + + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + sc.setDepth(16, 24); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); + mRender = new RsBenchRS(); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mRS != null) { + mRS = null; + destroyRenderScriptGL(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + return super.onKeyDown(keyCode, event); + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) { + boolean ret = false; + int act = ev.getAction(); + if (act == ev.ACTION_DOWN) { + mRender.onActionDown((int)ev.getX(), (int)ev.getY()); + ret = true; + } + + return ret; + } +} + + diff --git a/libs/rs/java/Samples/src/com/android/samples/RsList.java b/libs/rs/java/Samples/src/com/android/samples/RsList.java new file mode 100644 index 0000000..d47be42 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsList.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +public class RsList extends Activity { + + private RsListView mView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new RsListView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity loses focus + super.onResume(); + mView.resume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity loses focus + super.onPause(); + mView.pause(); + } + +} + diff --git a/libs/rs/java/Samples/src/com/android/samples/RsListRS.java b/libs/rs/java/Samples/src/com/android/samples/RsListRS.java new file mode 100644 index 0000000..8e2d51f --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsListRS.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import java.io.Writer; +import java.util.Vector; + +import android.content.res.Resources; +import android.renderscript.*; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + + +public class RsListRS { + + private final int STATE_LAST_FOCUS = 1; + + private static final String[] DATA_LIST = { + "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", + "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", + "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", + "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", + "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", + "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", + "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria", + "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde", + "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", + "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", + "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", + "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic", + "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", + "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland", + "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia", + "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar", + "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau", + "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary", + "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica", + "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos", + "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", + "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", + "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova", + "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", + "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", + "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas", + "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", + "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar", + "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena", + "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon", + "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal", + "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", + "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea", + "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", + "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas", + "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", + "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda", + "Ukraine", "United Arab Emirates", "United Kingdom", + "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", + "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara", + "Yemen", "Yugoslavia", "Zambia", "Zimbabwe" + }; + + int mWidth; + int mHeight; + + public RsListRS() { + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + initRS(); + } + + private Resources mRes; + private RenderScriptGL mRS; + private Font mItalic; + + ScriptField_ListAllocs_s mListAllocs; + + private ScriptC_rslist mScript; + + int mLastX; + int mLastY; + + public void onActionDown(int x, int y) { + mScript.set_gDY(0.0f); + + mLastX = x; + mLastY = y; + } + + public void onActionMove(int x, int y) { + int dx = mLastX - x; + int dy = mLastY - y; + + if (Math.abs(dy) <= 2) { + dy = 0; + } + + mScript.set_gDY(dy); + + mLastX = x; + mLastY = y; + } + + private void initRS() { + + mScript = new ScriptC_rslist(mRS, mRes, R.raw.rslist); + + mListAllocs = new ScriptField_ListAllocs_s(mRS, DATA_LIST.length); + for (int i = 0; i < DATA_LIST.length; i ++) { + ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item(); + listElem.text = Allocation.createFromString(mRS, DATA_LIST[i], Allocation.USAGE_SCRIPT); + mListAllocs.set(listElem, i, false); + } + + mListAllocs.copyAll(); + + mScript.bind_gList(mListAllocs); + + mItalic = Font.create(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8); + mScript.set_gItalic(mItalic); + + mRS.bindRootScript(mScript); + } +} + + + diff --git a/libs/rs/java/Samples/src/com/android/samples/RsListView.java b/libs/rs/java/Samples/src/com/android/samples/RsListView.java new file mode 100644 index 0000000..00b1723 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsListView.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class RsListView extends RSSurfaceView { + + public RsListView(Context context) { + super(context); + //setFocusable(true); + } + + private RenderScriptGL mRS; + private RsListRS mRender; + + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + sc.setDepth(16, 24); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); + mRender = new RsListRS(); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mRS != null) { + mRS = null; + destroyRenderScriptGL(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + // break point at here + // this method doesn't work when 'extends View' include 'extends ScrollView'. + return super.onKeyDown(keyCode, event); + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) + { + boolean ret = false; + int act = ev.getAction(); + if (act == ev.ACTION_DOWN) { + mRender.onActionDown((int)ev.getX(), (int)ev.getY()); + ret = true; + } else if (act == ev.ACTION_MOVE) { + mRender.onActionMove((int)ev.getX(), (int)ev.getY()); + ret = true; + } + + return ret; + } +} + + diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStates.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStates.java new file mode 100644 index 0000000..33c1719 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStates.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +public class RsRenderStates extends Activity { + + private RsRenderStatesView mView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new RsRenderStatesView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mView.resume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mView.pause(); + } + +} + diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java new file mode 100644 index 0000000..87840a7 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import java.io.Writer; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.renderscript.*; +import android.renderscript.Font.Style; +import android.renderscript.Program.TextureType; +import android.renderscript.ProgramStore.DepthFunc; +import android.renderscript.ProgramStore.BlendSrcFunc; +import android.renderscript.ProgramStore.BlendDstFunc; +import android.renderscript.Sampler.Value; +import android.util.Log; + + +public class RsRenderStatesRS { + + int mWidth; + int mHeight; + + public RsRenderStatesRS() { + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + mOptionsARGB.inScaled = false; + mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888; + mMode = 0; + mMaxModes = 0; + initRS(); + } + + private Resources mRes; + private RenderScriptGL mRS; + + private Sampler mLinearClamp; + private Sampler mLinearWrap; + private Sampler mMipLinearWrap; + private Sampler mNearestClamp; + private Sampler mMipLinearAniso8; + private Sampler mMipLinearAniso15; + + private ProgramStore mProgStoreBlendNoneDepth; + private ProgramStore mProgStoreBlendNone; + private ProgramStore mProgStoreBlendAlpha; + private ProgramStore mProgStoreBlendAdd; + + private ProgramFragment mProgFragmentTexture; + private ProgramFragment mProgFragmentColor; + + private ProgramVertex mProgVertex; + private ProgramVertexFixedFunction.Constants mPVA; + + // Custom shaders + private ProgramVertex mProgVertexCustom; + private ProgramFragment mProgFragmentCustom; + private ProgramFragment mProgFragmentMultitex; + private ScriptField_VertexShaderConstants_s mVSConst; + private ScriptField_VertexShaderConstants2_s mVSConst2; + private ScriptField_FragentShaderConstants_s mFSConst; + private ScriptField_FragentShaderConstants2_s mFSConst2; + + private ProgramVertex mProgVertexCustom2; + private ProgramFragment mProgFragmentCustom2; + + private ProgramVertex mProgVertexCube; + private ProgramFragment mProgFragmentCube; + + private ProgramRaster mCullBack; + private ProgramRaster mCullFront; + private ProgramRaster mCullNone; + + private Allocation mTexTorus; + private Allocation mTexOpaque; + private Allocation mTexTransparent; + private Allocation mTexChecker; + private Allocation mTexCube; + + private Mesh mMbyNMesh; + private Mesh mTorus; + + Font mFontSans; + Font mFontSerif; + Font mFontSerifBold; + Font mFontSerifItalic; + Font mFontSerifBoldItalic; + Font mFontMono; + private Allocation mTextAlloc; + + private ScriptC_rsrenderstates mScript; + + private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options(); + + int mMode; + int mMaxModes; + + public void onActionDown(int x, int y) { + mMode ++; + mMode = mMode % mMaxModes; + mScript.set_gDisplayMode(mMode); + } + + ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) { + ProgramStore.Builder builder = new ProgramStore.Builder(rs); + builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); + builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE); + builder.setDitherEnabled(false); + builder.setDepthMaskEnabled(false); + return builder.create(); + } + + private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) { + + Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS, + 2, Mesh.TriangleMeshBuilder.TEXTURE_0); + + for (int y = 0; y <= hResolution; y++) { + final float normalizedY = (float)y / hResolution; + final float yOffset = (normalizedY - 0.5f) * height; + for (int x = 0; x <= wResolution; x++) { + float normalizedX = (float)x / wResolution; + float xOffset = (normalizedX - 0.5f) * width; + tmb.setTexture(normalizedX, normalizedY); + tmb.addVertex(xOffset, yOffset); + } + } + + for (int y = 0; y < hResolution; y++) { + final int curY = y * (wResolution + 1); + final int belowY = (y + 1) * (wResolution + 1); + for (int x = 0; x < wResolution; x++) { + int curV = curY + x; + int belowV = belowY + x; + tmb.addTriangle(curV, belowV, curV + 1); + tmb.addTriangle(belowV, belowV + 1, curV + 1); + } + } + + return tmb.create(true); + } + + private void initProgramStore() { + // Use stock the stock program store object + mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS); + mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS); + + // Create a custom program store + ProgramStore.Builder builder = new ProgramStore.Builder(mRS); + builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); + builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA, + ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA); + builder.setDitherEnabled(false); + builder.setDepthMaskEnabled(false); + mProgStoreBlendAlpha = builder.create(); + + mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS); + + mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth); + mScript.set_gProgStoreBlendNone(mProgStoreBlendNone); + mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha); + mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd); + } + + private void initProgramFragment() { + + ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS); + texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, + ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); + mProgFragmentTexture = texBuilder.create(); + mProgFragmentTexture.bindSampler(mLinearClamp, 0); + + ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS); + colBuilder.setVaryingColor(false); + mProgFragmentColor = colBuilder.create(); + + mScript.set_gProgFragmentColor(mProgFragmentColor); + mScript.set_gProgFragmentTexture(mProgFragmentTexture); + } + + private void initProgramVertex() { + ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); + mProgVertex = pvb.create(); + + mPVA = new ProgramVertexFixedFunction.Constants(mRS); + ((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA); + Matrix4f proj = new Matrix4f(); + proj.loadOrthoWindow(mWidth, mHeight); + mPVA.setProjection(proj); + + mScript.set_gProgVertex(mProgVertex); + } + + private void initCustomShaders() { + mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1); + mVSConst2 = new ScriptField_VertexShaderConstants2_s(mRS, 1); + mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1); + mFSConst2 = new ScriptField_FragentShaderConstants2_s(mRS, 1); + + mScript.bind_gVSConstants(mVSConst); + mScript.bind_gVSConstants2(mVSConst2); + mScript.bind_gFSConstants(mFSConst); + mScript.bind_gFSConstants2(mFSConst2); + + // Initialize the shader builder + ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS); + // Specify the resource that contains the shader string + pvbCustom.setShader(mRes, R.raw.shaderv); + // Use a script field to spcify the input layout + pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + // Define the constant input layout + pvbCustom.addConstant(mVSConst.getAllocation().getType()); + mProgVertexCustom = pvbCustom.create(); + // Bind the source of constant data + mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0); + + ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS); + // Specify the resource that contains the shader string + pfbCustom.setShader(mRes, R.raw.shaderf); + //Tell the builder how many textures we have + pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); + // Define the constant input layout + pfbCustom.addConstant(mFSConst.getAllocation().getType()); + mProgFragmentCustom = pfbCustom.create(); + // Bind the source of constant data + mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0); + + pvbCustom = new ProgramVertex.Builder(mRS); + pvbCustom.setShader(mRes, R.raw.shaderarrayv); + pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + pvbCustom.addConstant(mVSConst2.getAllocation().getType()); + mProgVertexCustom2 = pvbCustom.create(); + mProgVertexCustom2.bindConstants(mVSConst2.getAllocation(), 0); + + pfbCustom = new ProgramFragment.Builder(mRS); + pfbCustom.setShader(mRes, R.raw.shaderarrayf); + pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); + pfbCustom.addConstant(mFSConst2.getAllocation().getType()); + mProgFragmentCustom2 = pfbCustom.create(); + mProgFragmentCustom2.bindConstants(mFSConst2.getAllocation(), 0); + + // Cubemap test shaders + pvbCustom = new ProgramVertex.Builder(mRS); + pvbCustom.setShader(mRes, R.raw.shadercubev); + pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + pvbCustom.addConstant(mVSConst.getAllocation().getType()); + mProgVertexCube = pvbCustom.create(); + mProgVertexCube.bindConstants(mVSConst.getAllocation(), 0); + + pfbCustom = new ProgramFragment.Builder(mRS); + pfbCustom.setShader(mRes, R.raw.shadercubef); + pfbCustom.addTexture(Program.TextureType.TEXTURE_CUBE); + mProgFragmentCube = pfbCustom.create(); + + pfbCustom = new ProgramFragment.Builder(mRS); + pfbCustom.setShader(mRes, R.raw.multitexf); + for (int texCount = 0; texCount < 3; texCount ++) { + pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); + } + mProgFragmentMultitex = pfbCustom.create(); + + mScript.set_gProgVertexCustom(mProgVertexCustom); + mScript.set_gProgFragmentCustom(mProgFragmentCustom); + mScript.set_gProgVertexCustom2(mProgVertexCustom2); + mScript.set_gProgFragmentCustom2(mProgFragmentCustom2); + mScript.set_gProgVertexCube(mProgVertexCube); + mScript.set_gProgFragmentCube(mProgFragmentCube); + mScript.set_gProgFragmentMultitex(mProgFragmentMultitex); + } + + private Allocation loadTextureRGB(int id) { + return Allocation.createFromBitmapResource(mRS, mRes, id, + Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + } + + private Allocation loadTextureARGB(int id) { + Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB); + return Allocation.createFromBitmap(mRS, b, + Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + } + + private void loadImages() { + mTexTorus = loadTextureRGB(R.drawable.torusmap); + mTexOpaque = loadTextureRGB(R.drawable.data); + mTexTransparent = loadTextureARGB(R.drawable.leaf); + mTexChecker = loadTextureRGB(R.drawable.checker); + Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test); + mTexCube = Allocation.createCubemapFromBitmap(mRS, b); + + mScript.set_gTexTorus(mTexTorus); + mScript.set_gTexOpaque(mTexOpaque); + mScript.set_gTexTransparent(mTexTransparent); + mScript.set_gTexChecker(mTexChecker); + mScript.set_gTexCube(mTexCube); + } + + private void initFonts() { + // Sans font by family name + mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8); + mFontSerif = Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8); + // Create fonts by family and style + mFontSerifBold = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8); + mFontSerifItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8); + mFontSerifBoldItalic = Font.create(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8); + mFontMono = Font.create(mRS, mRes, "mono", Font.Style.NORMAL, 8); + + mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT); + + mScript.set_gFontSans(mFontSans); + mScript.set_gFontSerif(mFontSerif); + mScript.set_gFontSerifBold(mFontSerifBold); + mScript.set_gFontSerifItalic(mFontSerifItalic); + mScript.set_gFontSerifBoldItalic(mFontSerifBoldItalic); + mScript.set_gFontMono(mFontMono); + mScript.set_gTextAlloc(mTextAlloc); + } + + private void initMesh() { + mMbyNMesh = getMbyNMesh(256, 256, 10, 10); + mScript.set_gMbyNMesh(mMbyNMesh); + + FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus); + FileA3D.IndexEntry entry = model.getIndexEntry(0); + if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) { + Log.e("rs", "could not load model"); + } else { + mTorus = (Mesh)entry.getObject(); + mScript.set_gTorusMesh(mTorus); + } + } + + private void initSamplers() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMinification(Sampler.Value.LINEAR); + bs.setMagnification(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.WRAP); + bs.setWrapT(Sampler.Value.WRAP); + mLinearWrap = bs.create(); + + mLinearClamp = Sampler.CLAMP_LINEAR(mRS); + mNearestClamp = Sampler.CLAMP_NEAREST(mRS); + mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS); + + bs = new Sampler.Builder(mRS); + bs.setMinification(Sampler.Value.LINEAR_MIP_LINEAR); + bs.setMagnification(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.WRAP); + bs.setWrapT(Sampler.Value.WRAP); + bs.setAnisotropy(8.0f); + mMipLinearAniso8 = bs.create(); + bs.setAnisotropy(15.0f); + mMipLinearAniso15 = bs.create(); + + mScript.set_gLinearClamp(mLinearClamp); + mScript.set_gLinearWrap(mLinearWrap); + mScript.set_gMipLinearWrap(mMipLinearWrap); + mScript.set_gMipLinearAniso8(mMipLinearAniso8); + mScript.set_gMipLinearAniso15(mMipLinearAniso15); + mScript.set_gNearestClamp(mNearestClamp); + } + + private void initProgramRaster() { + mCullBack = ProgramRaster.CULL_BACK(mRS); + mCullFront = ProgramRaster.CULL_FRONT(mRS); + mCullNone = ProgramRaster.CULL_NONE(mRS); + + mScript.set_gCullBack(mCullBack); + mScript.set_gCullFront(mCullFront); + mScript.set_gCullNone(mCullNone); + } + + private void initRS() { + + mScript = new ScriptC_rsrenderstates(mRS, mRes, R.raw.rsrenderstates); + + mMaxModes = mScript.get_gMaxModes(); + + initSamplers(); + initProgramStore(); + initProgramFragment(); + initProgramVertex(); + initFonts(); + loadImages(); + initMesh(); + initProgramRaster(); + initCustomShaders(); + + mRS.bindRootScript(mScript); + } +} + + + diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesView.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesView.java new file mode 100644 index 0000000..235d29b --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesView.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.samples; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class RsRenderStatesView extends RSSurfaceView { + + public RsRenderStatesView(Context context) { + super(context); + //setFocusable(true); + } + + private RenderScriptGL mRS; + private RsRenderStatesRS mRender; + + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + sc.setDepth(16, 24); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); + mRender = new RsRenderStatesRS(); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mRS != null) { + mRS = null; + destroyRenderScriptGL(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + // break point at here + // this method doesn't work when 'extends View' include 'extends ScrollView'. + return super.onKeyDown(keyCode, event); + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) + { + boolean ret = false; + int act = ev.getAction(); + if (act == ev.ACTION_DOWN) { + mRender.onActionDown((int)ev.getX(), (int)ev.getY()); + ret = true; + } + + return ret; + } +} + + diff --git a/libs/rs/java/Samples/src/com/android/samples/rsbench.rs b/libs/rs/java/Samples/src/com/android/samples/rsbench.rs new file mode 100644 index 0000000..905f34b --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/rsbench.rs @@ -0,0 +1,789 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.samples) + +#include "rs_graphics.rsh" +#include "shader_def.rsh" + +const int gMaxModes = 26; + +rs_program_vertex gProgVertex; +rs_program_fragment gProgFragmentColor; +rs_program_fragment gProgFragmentTexture; + +rs_program_store gProgStoreBlendNoneDepth; +rs_program_store gProgStoreBlendNone; +rs_program_store gProgStoreBlendAlpha; +rs_program_store gProgStoreBlendAdd; + +rs_allocation gTexOpaque; +rs_allocation gTexTorus; +rs_allocation gTexTransparent; +rs_allocation gTexChecker; +rs_allocation gTexCube; + +rs_mesh g10by10Mesh; +rs_mesh g100by100Mesh; +rs_mesh gWbyHMesh; +rs_mesh gTorusMesh; + +rs_font gFontSans; +rs_font gFontSerif; +rs_font gFontSerifBold; +rs_font gFontSerifItalic; +rs_font gFontSerifBoldItalic; +rs_font gFontMono; +rs_allocation gTextAlloc; + +int gDisplayMode; + +rs_sampler gLinearClamp; +rs_sampler gLinearWrap; +rs_sampler gMipLinearWrap; +rs_sampler gMipLinearAniso8; +rs_sampler gMipLinearAniso15; +rs_sampler gNearestClamp; + +rs_program_raster gCullBack; +rs_program_raster gCullFront; +rs_program_raster gCullNone; + +// Custom vertex shader compunents +VertexShaderConstants *gVSConstants; +FragentShaderConstants *gFSConstants; +VertexShaderConstants3 *gVSConstPixel; +FragentShaderConstants3 *gFSConstPixel; +// Export these out to easily set the inputs to shader +VertexShaderInputs *gVSInputs; +// Custom shaders we use for lighting +rs_program_vertex gProgVertexCustom; +rs_program_fragment gProgFragmentCustom; +rs_program_vertex gProgVertexPixelLight; +rs_program_vertex gProgVertexPixelLightMove; +rs_program_fragment gProgFragmentPixelLight; +rs_program_vertex gProgVertexCube; +rs_program_fragment gProgFragmentCube; +rs_program_fragment gProgFragmentMultitex; + +float gDt = 0; + +void init() { +} + +static const char *sampleText = "This is a sample of small text for performace"; +// Offsets for multiple layer of text +static int textOffsets[] = { 0, 0, -5, -5, 5, 5, -8, -8, 8, 8}; +static float textColors[] = {1.0f, 1.0f, 1.0f, 1.0f, + 0.5f, 0.7f, 0.5f, 1.0f, + 0.7f, 0.5f, 0.5f, 1.0f, + 0.5f, 0.5f, 0.7f, 1.0f, + 0.5f, 0.6f, 0.7f, 1.0f, +}; + +static void displayFontSamples(int fillNum) { + + rs_font fonts[5]; + rsSetObject(&fonts[0], gFontSans); + rsSetObject(&fonts[1], gFontSerif); + rsSetObject(&fonts[2], gFontSerifBold); + rsSetObject(&fonts[3], gFontSerifBoldItalic); + rsSetObject(&fonts[4], gFontSans); + + uint width = rsgGetWidth(); + uint height = rsgGetHeight(); + int left = 0, right = 0, top = 0, bottom = 0; + rsgMeasureText(sampleText, &left, &right, &top, &bottom); + + int textHeight = top - bottom; + int textWidth = right - left; + int numVerticalLines = height / textHeight; + int yPos = top; + + int xOffset = 0, yOffset = 0; + for(int fillI = 0; fillI < fillNum; fillI ++) { + rsgBindFont(fonts[fillI]); + xOffset = textOffsets[fillI * 2]; + yOffset = textOffsets[fillI * 2 + 1]; + float *colPtr = textColors + fillI * 4; + rsgFontColor(colPtr[0], colPtr[1], colPtr[2], colPtr[3]); + for (int h = 0; h < 4; h ++) { + yPos = top + yOffset; + for (int v = 0; v < numVerticalLines; v ++) { + rsgDrawText(sampleText, xOffset + textWidth * h, yPos); + yPos += textHeight; + } + } + } + + for (int i = 0; i < 5; i ++) { + rsClearObject(&fonts[i]); + } +} + +static void bindProgramVertexOrtho() { + // Default vertex sahder + rsgBindProgramVertex(gProgVertex); + // Setup the projection matrix + rs_matrix4x4 proj; + rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500); + rsgProgramVertexLoadProjectionMatrix(&proj); +} + +static void displaySingletexFill(bool blend, int quadCount) { + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + + // Fragment shader with texture + if (!blend) { + rsgBindProgramStore(gProgStoreBlendNone); + } else { + rsgBindProgramStore(gProgStoreBlendAlpha); + } + rsgBindProgramFragment(gProgFragmentTexture); + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); + + for (int i = 0; i < quadCount; i ++) { + float startX = 10 * i, startY = 10 * i; + float width = rsgGetWidth() - startX, height = rsgGetHeight() - startY; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1, + startX + width, startY + height, 0, 1, 1, + startX + width, startY, 0, 1, 0); + } +} + +static void displayBlendingSamples() { + int i; + + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + + rsgBindProgramFragment(gProgFragmentColor); + + rsgBindProgramStore(gProgStoreBlendNone); + for (i = 0; i < 3; i ++) { + float iPlusOne = (float)(i + 1); + rsgProgramFragmentConstantColor(gProgFragmentColor, + 0.1f*iPlusOne, 0.2f*iPlusOne, 0.3f*iPlusOne, 1); + float yPos = 150 * (float)i; + rsgDrawRect(0, yPos, 200, yPos + 200, 0); + } + + rsgBindProgramStore(gProgStoreBlendAlpha); + for (i = 0; i < 3; i ++) { + float iPlusOne = (float)(i + 1); + rsgProgramFragmentConstantColor(gProgFragmentColor, + 0.2f*iPlusOne, 0.3f*iPlusOne, 0.1f*iPlusOne, 0.5); + float yPos = 150 * (float)i; + rsgDrawRect(150, yPos, 350, yPos + 200, 0); + } + + rsgBindProgramStore(gProgStoreBlendAdd); + for (i = 0; i < 3; i ++) { + float iPlusOne = (float)(i + 1); + rsgProgramFragmentConstantColor(gProgFragmentColor, + 0.3f*iPlusOne, 0.1f*iPlusOne, 0.2f*iPlusOne, 0.5); + float yPos = 150 * (float)i; + rsgDrawRect(300, yPos, 500, yPos + 200, 0); + } + + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("No Blending", 10, 50); + rsgDrawText("Alpha Blending", 160, 150); + rsgDrawText("Additive Blending", 320, 250); + +} + +static void displayMeshSamples(int meshNum) { + + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadTranslate(&matrix, rsgGetWidth()/2, rsgGetHeight()/2, 0); + rsgProgramVertexLoadModelMatrix(&matrix); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNone); + rsgBindProgramFragment(gProgFragmentTexture); + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); + + if (meshNum == 0) { + rsgDrawMesh(g10by10Mesh); + } else if (meshNum == 1) { + rsgDrawMesh(g100by100Mesh); + } else if (meshNum == 2) { + rsgDrawMesh(gWbyHMesh); + } +} + +static void displayTextureSamplers() { + + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNone); + rsgBindProgramFragment(gProgFragmentTexture); + rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); + + // Linear clamp + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + float startX = 0, startY = 0; + float width = 300, height = 300; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1.1, + startX + width, startY + height, 0, 1.1, 1.1, + startX + width, startY, 0, 1.1, 0); + + // Linear Wrap + rsgBindSampler(gProgFragmentTexture, 0, gLinearWrap); + startX = 0; startY = 300; + width = 300; height = 300; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1.1, + startX + width, startY + height, 0, 1.1, 1.1, + startX + width, startY, 0, 1.1, 0); + + // Nearest + rsgBindSampler(gProgFragmentTexture, 0, gNearestClamp); + startX = 300; startY = 0; + width = 300; height = 300; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1.1, + startX + width, startY + height, 0, 1.1, 1.1, + startX + width, startY, 0, 1.1, 0); + + rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap); + startX = 300; startY = 300; + width = 300; height = 300; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1.5, + startX + width, startY + height, 0, 1.5, 1.5, + startX + width, startY, 0, 1.5, 0); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Filtering: linear clamp", 10, 290); + rsgDrawText("Filtering: linear wrap", 10, 590); + rsgDrawText("Filtering: nearest clamp", 310, 290); + rsgDrawText("Filtering: miplinear wrap", 310, 590); +} + +static float gTorusRotation = 0; +static void updateModelMatrix(rs_matrix4x4 *matrix, void *buffer) { + if (buffer == 0) { + rsgProgramVertexLoadModelMatrix(matrix); + } else { + rsAllocationMarkDirty(rsGetAllocation(buffer)); + } +} + +static void drawToruses(int numMeshes, rs_matrix4x4 *matrix, void *buffer) { + + if (numMeshes == 1) { + rsMatrixLoadTranslate(matrix, 0.0f, 0.0f, -7.5f); + rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f); + updateModelMatrix(matrix, buffer); + rsgDrawMesh(gTorusMesh); + return; + } + + if (numMeshes == 2) { + rsMatrixLoadTranslate(matrix, -1.6f, 0.0f, -7.5f); + rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f); + updateModelMatrix(matrix, buffer); + rsgDrawMesh(gTorusMesh); + + rsMatrixLoadTranslate(matrix, 1.6f, 0.0f, -7.5f); + rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f); + updateModelMatrix(matrix, buffer); + rsgDrawMesh(gTorusMesh); + return; + } + + float startX = -5.0f; + float startY = -1.5f; + float startZ = -15.0f; + float dist = 3.2f; + + for (int h = 0; h < 4; h ++) { + for (int v = 0; v < 2; v ++) { + // Position our model on the screen + rsMatrixLoadTranslate(matrix, startX + dist * h, startY + dist * v, startZ); + rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f); + updateModelMatrix(matrix, buffer); + rsgDrawMesh(gTorusMesh); + } + } +} + + +// Quick hack to get some geometry numbers +static void displaySimpleGeoSamples(bool useTexture, int numMeshes) { + rsgBindProgramVertex(gProgVertex); + rsgBindProgramRaster(gCullBack); + // Setup the projection matrix with 30 degree field of view + rs_matrix4x4 proj; + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNoneDepth); + if (useTexture) { + rsgBindProgramFragment(gProgFragmentTexture); + } else { + rsgBindProgramFragment(gProgFragmentColor); + rsgProgramFragmentConstantColor(gProgFragmentColor, 0.1, 0.7, 0.1, 1); + } + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + rsgBindTexture(gProgFragmentTexture, 0, gTexTorus); + + // Apply a rotation to our mesh + gTorusRotation += 50.0f * gDt; + if (gTorusRotation > 360.0f) { + gTorusRotation -= 360.0f; + } + + rs_matrix4x4 matrix; + drawToruses(numMeshes, &matrix, 0); +} + +float gLight0Rotation = 0; +float gLight1Rotation = 0; + +static void setupCustomShaderLights() { + float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f}; + float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f}; + float4 light0DiffCol = {0.9f, 0.7f, 0.7f, 1.0f}; + float4 light0SpecCol = {0.9f, 0.6f, 0.6f, 1.0f}; + float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f}; + float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f}; + + gLight0Rotation += 50.0f * gDt; + if (gLight0Rotation > 360.0f) { + gLight0Rotation -= 360.0f; + } + gLight1Rotation -= 50.0f * gDt; + if (gLight1Rotation > 360.0f) { + gLight1Rotation -= 360.0f; + } + + rs_matrix4x4 l0Mat; + rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f); + light0Pos = rsMatrixMultiply(&l0Mat, light0Pos); + rs_matrix4x4 l1Mat; + rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f); + light1Pos = rsMatrixMultiply(&l1Mat, light1Pos); + + // Set light 0 properties + gVSConstants->light0_Posision = light0Pos; + gVSConstants->light0_Diffuse = 1.0f; + gVSConstants->light0_Specular = 0.5f; + gVSConstants->light0_CosinePower = 10.0f; + // Set light 1 properties + gVSConstants->light1_Posision = light1Pos; + gVSConstants->light1_Diffuse = 1.0f; + gVSConstants->light1_Specular = 0.7f; + gVSConstants->light1_CosinePower = 25.0f; + rsAllocationMarkDirty(rsGetAllocation(gVSConstants)); + + // Update fragment shader constants + // Set light 0 colors + gFSConstants->light0_DiffuseColor = light0DiffCol; + gFSConstants->light0_SpecularColor = light0SpecCol; + // Set light 1 colors + gFSConstants->light1_DiffuseColor = light1DiffCol; + gFSConstants->light1_SpecularColor = light1SpecCol; + rsAllocationMarkDirty(rsGetAllocation(gFSConstants)); + + // Set light 0 properties for per pixel lighting + gFSConstPixel->light0_Posision = light0Pos; + gFSConstPixel->light0_Diffuse = 1.0f; + gFSConstPixel->light0_Specular = 0.5f; + gFSConstPixel->light0_CosinePower = 10.0f; + gFSConstPixel->light0_DiffuseColor = light0DiffCol; + gFSConstPixel->light0_SpecularColor = light0SpecCol; + // Set light 1 properties + gFSConstPixel->light1_Posision = light1Pos; + gFSConstPixel->light1_Diffuse = 1.0f; + gFSConstPixel->light1_Specular = 0.7f; + gFSConstPixel->light1_CosinePower = 25.0f; + gFSConstPixel->light1_DiffuseColor = light1DiffCol; + gFSConstPixel->light1_SpecularColor = light1SpecCol; + rsAllocationMarkDirty(rsGetAllocation(gFSConstPixel)); +} + +static void displayCustomShaderSamples(int numMeshes) { + + // Update vertex shader constants + // Load model matrix + // Apply a rotation to our mesh + gTorusRotation += 50.0f * gDt; + if (gTorusRotation > 360.0f) { + gTorusRotation -= 360.0f; + } + + // Setup the projection matrix + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f); + setupCustomShaderLights(); + + rsgBindProgramVertex(gProgVertexCustom); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNoneDepth); + rsgBindProgramFragment(gProgFragmentCustom); + rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp); + rsgBindTexture(gProgFragmentCustom, 0, gTexTorus); + + // Use back face culling + rsgBindProgramRaster(gCullBack); + + drawToruses(numMeshes, &gVSConstants->model, gVSConstants); +} + +static void displayPixelLightSamples(int numMeshes, bool heavyVertex) { + + // Update vertex shader constants + // Load model matrix + // Apply a rotation to our mesh + gTorusRotation += 30.0f * gDt; + if (gTorusRotation > 360.0f) { + gTorusRotation -= 360.0f; + } + + gVSConstPixel->time = rsUptimeMillis()*0.005; + + // Setup the projection matrix + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&gVSConstPixel->proj, 30.0f, aspect, 0.1f, 100.0f); + setupCustomShaderLights(); + + if (heavyVertex) { + rsgBindProgramVertex(gProgVertexPixelLightMove); + } else { + rsgBindProgramVertex(gProgVertexPixelLight); + } + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNoneDepth); + rsgBindProgramFragment(gProgFragmentPixelLight); + rsgBindSampler(gProgFragmentPixelLight, 0, gLinearClamp); + rsgBindTexture(gProgFragmentPixelLight, 0, gTexTorus); + + // Use back face culling + rsgBindProgramRaster(gCullBack); + + drawToruses(numMeshes, &gVSConstPixel->model, gVSConstPixel); +} + +static void displayMultitextureSample(bool blend, int quadCount) { + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + + // Fragment shader with texture + if (!blend) { + rsgBindProgramStore(gProgStoreBlendNone); + } else { + rsgBindProgramStore(gProgStoreBlendAlpha); + } + rsgBindProgramFragment(gProgFragmentMultitex); + rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp); + rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap); + rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp); + rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker); + rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus); + rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent); + + for (int i = 0; i < quadCount; i ++) { + float startX = 10 * i, startY = 10 * i; + float width = rsgGetWidth() - startX, height = rsgGetHeight() - startY; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1, + startX + width, startY + height, 0, 1, 1, + startX + width, startY, 0, 1, 0); + } +} + +static float gAnisoTime = 0.0f; +static uint anisoMode = 0; +static void displayAnisoSample() { + + gAnisoTime += gDt; + + rsgBindProgramVertex(gProgVertex); + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rs_matrix4x4 proj; + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + rs_matrix4x4 matrix; + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNone); + rsgBindProgramFragment(gProgFragmentTexture); + rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, -10.0f); + rsMatrixRotate(&matrix, -80, 1.0f, 0.0f, 0.0f); + rsgProgramVertexLoadModelMatrix(&matrix); + + rsgBindProgramRaster(gCullNone); + + rsgBindTexture(gProgFragmentTexture, 0, gTexChecker); + + if (gAnisoTime >= 5.0f) { + gAnisoTime = 0.0f; + anisoMode ++; + anisoMode = anisoMode % 3; + } + + if (anisoMode == 0) { + rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso8); + } else if (anisoMode == 1) { + rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso15); + } else { + rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap); + } + + float startX = -15; + float startY = -15; + float width = 30; + float height = 30; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 10, + startX + width, startY + height, 0, 10, 10, + startX + width, startY, 0, 10, 0); + + rsgBindProgramRaster(gCullBack); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + if (anisoMode == 0) { + rsgDrawText("Anisotropic filtering 8", 10, 40); + } else if (anisoMode == 1) { + rsgDrawText("Anisotropic filtering 15", 10, 40); + } else { + rsgDrawText("Miplinear filtering", 10, 40); + } +} + +static bool checkInit() { + + static int countdown = 5; + + if (countdown == 0) { + gDt = 0; + countdown --; + } + // Perform all the uploads so we only measure rendered time + if(countdown > 1) { + displayFontSamples(5); + displaySingletexFill(true, 3); + displayBlendingSamples(); + displayMeshSamples(0); + displayMeshSamples(1); + displayMeshSamples(2); + displayTextureSamplers(); + displayMultitextureSample(true, 5); + displayAnisoSample(); + displayPixelLightSamples(1, false); + displayPixelLightSamples(1, true); + countdown --; + rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); + + // Now use text metrics to center the text + uint width = rsgGetWidth(); + uint height = rsgGetHeight(); + int left = 0, right = 0, top = 0, bottom = 0; + + rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); + rsgBindFont(gFontSerifBoldItalic); + + const char* text = "Initializing"; + rsgMeasureText(text, &left, &right, &top, &bottom); + int centeredPosX = width / 2 - (right - left) / 2; + int centeredPosY = height / 2 - (top - bottom) / 2; + rsgDrawText(text, centeredPosX, centeredPosY); + + return false; + } + + return true; +} + +static int frameCount = 0; +static int totalFramesRendered = 0; +static int benchMode = 0; + +#define testTime 5.0f +static float curTestTime = testTime; + +static const char *testNames[] = { + "Finished text fill 1", + "Finished text fill 2", + "Finished text fill 3", + "Finished text fill 4", + "Finished text fill 5", + "Finished 25.6k geo flat color", + "Finished 51.2k geo flat color", + "Finished 204.8k geo raster load flat color", + "Finished 25.6k geo texture", + "Finished 51.2k geo texture", + "Finished 204.8k geo raster load texture", + "Finished full screen mesh 10 by 10", + "Finished full screen mesh 100 by 100", + "Finished full screen mesh W / 4 by H / 4", + "Finished 25.6k geo heavy vertex", + "Finished 51.2k geo heavy vertex", + "Finished 204.8k geo raster load heavy vertex", + "Finished singletexture 5x fill", + "Finished 3tex multitexture 5x fill", + "Finished blend singletexture 5x fill", + "Finished blend 3tex multitexture 5x fill", + "Finished 25.6k geo heavy fragment", + "Finished 51.2k geo heavy fragment", + "Finished 204.8k geo raster load heavy fragment", + "Finished 25.6k geo heavy fragment, heavy vertex", + "Finished 51.2k geo heavy fragment, heavy vertex", + "Finished 204.8k geo raster load heavy fragment, heavy vertex", +}; + +int root(int launchID) { + + gDt = rsGetDt(); + + rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); + rsgClearDepth(1.0f); + + if(!checkInit()) { + return 1; + } + + curTestTime -= gDt; + if(curTestTime < 0.0f) { + float fps = (float)(frameCount) / (testTime - curTestTime); + rsDebug(testNames[benchMode], fps); + benchMode ++; + curTestTime = testTime; + totalFramesRendered += frameCount; + frameCount = 0; + gTorusRotation = 0; + + if (benchMode > gMaxModes) { + benchMode = 0; + } + } + + switch (benchMode) { + case 0: + displayFontSamples(1); + break; + case 1: + displayFontSamples(2); + break; + case 2: + displayFontSamples(3); + break; + case 3: + displayFontSamples(4); + break; + case 4: + displayFontSamples(5); + break; + case 5: + displaySimpleGeoSamples(false, 1); + break; + case 6: + displaySimpleGeoSamples(false, 2); + break; + case 7: + displaySimpleGeoSamples(false, 8); + break; + case 8: + displaySimpleGeoSamples(true, 1); + break; + case 9: + displaySimpleGeoSamples(true, 2); + break; + case 10: + displaySimpleGeoSamples(true, 8); + break; + case 11: + displayMeshSamples(0); + break; + case 12: + displayMeshSamples(1); + break; + case 13: + displayMeshSamples(2); + break; + case 14: + displayCustomShaderSamples(1); + break; + case 15: + displayCustomShaderSamples(2); + break; + case 16: + displayCustomShaderSamples(8); + break; + case 17: + displaySingletexFill(false, 5); + break; + case 18: + displayMultitextureSample(false, 5); + break; + case 19: + displaySingletexFill(true, 5); + break; + case 20: + displayMultitextureSample(true, 5); + break; + case 21: + displayPixelLightSamples(1, false); + break; + case 22: + displayPixelLightSamples(2, false); + break; + case 23: + displayPixelLightSamples(8, false); + break; + case 24: + displayPixelLightSamples(1, true); + break; + case 25: + displayPixelLightSamples(2, true); + break; + case 26: + displayPixelLightSamples(8, true); + break; + + } + + frameCount ++; + + return 1; +} diff --git a/libs/rs/java/Samples/src/com/android/samples/rslist.rs b/libs/rs/java/Samples/src/com/android/samples/rslist.rs new file mode 100644 index 0000000..0baccb8 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/rslist.rs @@ -0,0 +1,72 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.samples) + +#include "rs_graphics.rsh" + +float gDY; + +rs_font gItalic; + +typedef struct ListAllocs_s { + rs_allocation text; +} ListAllocs; + +ListAllocs *gList; + +void init() { + gDY = 0.0f; +} + +int textPos = 0; + +int root(int launchID) { + + rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f); + rsgClearDepth(1.0f); + + textPos -= (int)gDY*2; + gDY *= 0.95; + + rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f); + rsgBindFont(gItalic); + color(0.2, 0.2, 0.2, 0); + + rs_allocation listAlloc; + rsSetObject(&listAlloc, rsGetAllocation(gList)); + int allocSize = rsAllocationGetDimX(listAlloc); + + int width = rsgGetWidth(); + int height = rsgGetHeight(); + + int itemHeight = 80; + int currentYPos = itemHeight + textPos; + + for (int i = 0; i < allocSize; i ++) { + if (currentYPos - itemHeight > height) { + break; + } + + if (currentYPos > 0) { + rsgDrawRect(0, currentYPos - 1, width, currentYPos, 0); + rsgDrawText(gList[i].text, 30, currentYPos - 32); + } + currentYPos += itemHeight; + } + + return 10; +} diff --git a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs new file mode 100644 index 0000000..a973167 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs @@ -0,0 +1,680 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.samples) + +#include "rs_graphics.rsh" +#include "shader_def.rsh" + +const int gMaxModes = 11; + +rs_program_vertex gProgVertex; +rs_program_fragment gProgFragmentColor; +rs_program_fragment gProgFragmentTexture; + +rs_program_store gProgStoreBlendNoneDepth; +rs_program_store gProgStoreBlendNone; +rs_program_store gProgStoreBlendAlpha; +rs_program_store gProgStoreBlendAdd; + +rs_allocation gTexOpaque; +rs_allocation gTexTorus; +rs_allocation gTexTransparent; +rs_allocation gTexChecker; +rs_allocation gTexCube; + +rs_mesh gMbyNMesh; +rs_mesh gTorusMesh; + +rs_font gFontSans; +rs_font gFontSerif; +rs_font gFontSerifBold; +rs_font gFontSerifItalic; +rs_font gFontSerifBoldItalic; +rs_font gFontMono; +rs_allocation gTextAlloc; + +int gDisplayMode; + +rs_sampler gLinearClamp; +rs_sampler gLinearWrap; +rs_sampler gMipLinearWrap; +rs_sampler gMipLinearAniso8; +rs_sampler gMipLinearAniso15; +rs_sampler gNearestClamp; + +rs_program_raster gCullBack; +rs_program_raster gCullFront; +rs_program_raster gCullNone; + +// Custom vertex shader compunents +VertexShaderConstants *gVSConstants; +VertexShaderConstants2 *gVSConstants2; +FragentShaderConstants *gFSConstants; +FragentShaderConstants2 *gFSConstants2; +// Export these out to easily set the inputs to shader +VertexShaderInputs *gVSInputs; +// Custom shaders we use for lighting +rs_program_vertex gProgVertexCustom; +rs_program_fragment gProgFragmentCustom; +rs_program_vertex gProgVertexCustom2; +rs_program_fragment gProgFragmentCustom2; +rs_program_vertex gProgVertexCube; +rs_program_fragment gProgFragmentCube; +rs_program_fragment gProgFragmentMultitex; + +float gDt = 0; + +void init() { +} + +static void displayFontSamples() { + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + int yPos = 100; + rsgBindFont(gFontSans); + rsgDrawText("Sans font sample", 30, yPos); + yPos += 30; + rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f); + rsgBindFont(gFontSerif); + rsgDrawText("Serif font sample", 30, yPos); + yPos += 30; + rsgFontColor(0.7f, 0.7f, 0.7f, 1.0f); + rsgBindFont(gFontSerifBold); + rsgDrawText("Serif Bold font sample", 30, yPos); + yPos += 30; + rsgFontColor(0.5f, 0.5f, 0.9f, 1.0f); + rsgBindFont(gFontSerifItalic); + rsgDrawText("Serif Italic font sample", 30, yPos); + yPos += 30; + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontSerifBoldItalic); + rsgDrawText("Serif Bold Italic font sample", 30, yPos); + yPos += 30; + rsgBindFont(gFontMono); + rsgDrawText("Monospace font sample", 30, yPos); + yPos += 50; + + // Now use text metrics to center the text + uint width = rsgGetWidth(); + uint height = rsgGetHeight(); + int left = 0, right = 0, top = 0, bottom = 0; + + rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); + rsgBindFont(gFontSerifBoldItalic); + + rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom); + int centeredPos = width / 2 - (right - left) / 2; + rsgDrawText(gTextAlloc, centeredPos, yPos); + yPos += 30; + + const char* text = "Centered Text Sample"; + rsgMeasureText(text, &left, &right, &top, &bottom); + centeredPos = width / 2 - (right - left) / 2; + rsgDrawText(text, centeredPos, yPos); + yPos += 30; + + rsgBindFont(gFontSans); + text = "More Centered Text Samples"; + rsgMeasureText(text, &left, &right, &top, &bottom); + centeredPos = width / 2 - (right - left) / 2; + rsgDrawText(text, centeredPos, yPos); + yPos += 30; + + // Now draw bottom and top right aligned text + text = "Top-right aligned text"; + rsgMeasureText(text, &left, &right, &top, &bottom); + rsgDrawText(text, width - right, top); + + text = "Top-left"; + rsgMeasureText(text, &left, &right, &top, &bottom); + rsgDrawText(text, -left, top); + + text = "Bottom-right aligned text"; + rsgMeasureText(text, &left, &right, &top, &bottom); + rsgDrawText(text, width - right, height + bottom); + +} + +static void bindProgramVertexOrtho() { + // Default vertex sahder + rsgBindProgramVertex(gProgVertex); + // Setup the projectioni matrix + rs_matrix4x4 proj; + rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500); + rsgProgramVertexLoadProjectionMatrix(&proj); +} + +static void displayShaderSamples() { + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNone); + rsgBindProgramFragment(gProgFragmentTexture); + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); + + float startX = 0, startY = 0; + float width = 256, height = 256; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1, + startX + width, startY + height, 0, 1, 1, + startX + width, startY, 0, 1, 0); + + startX = 200; startY = 0; + width = 128; height = 128; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1, + startX + width, startY + height, 0, 1, 1, + startX + width, startY, 0, 1, 0); + + rsgBindProgramStore(gProgStoreBlendAlpha); + rsgBindTexture(gProgFragmentTexture, 0, gTexTransparent); + startX = 0; startY = 200; + width = 128; height = 128; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1, + startX + width, startY + height, 0, 1, 1, + startX + width, startY, 0, 1, 0); + + // Fragment program with simple color + rsgBindProgramFragment(gProgFragmentColor); + rsgProgramFragmentConstantColor(gProgFragmentColor, 0.9, 0.3, 0.3, 1); + rsgDrawRect(200, 300, 350, 450, 0); + rsgProgramFragmentConstantColor(gProgFragmentColor, 0.3, 0.9, 0.3, 1); + rsgDrawRect(50, 400, 400, 600, 0); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Texture shader", 10, 50); + rsgDrawText("Alpha-blended texture shader", 10, 280); + rsgDrawText("Flat color shader", 100, 450); +} + +static void displayBlendingSamples() { + int i; + + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + + rsgBindProgramFragment(gProgFragmentColor); + + rsgBindProgramStore(gProgStoreBlendNone); + for (i = 0; i < 3; i ++) { + float iPlusOne = (float)(i + 1); + rsgProgramFragmentConstantColor(gProgFragmentColor, + 0.1f*iPlusOne, 0.2f*iPlusOne, 0.3f*iPlusOne, 1); + float yPos = 150 * (float)i; + rsgDrawRect(0, yPos, 200, yPos + 200, 0); + } + + rsgBindProgramStore(gProgStoreBlendAlpha); + for (i = 0; i < 3; i ++) { + float iPlusOne = (float)(i + 1); + rsgProgramFragmentConstantColor(gProgFragmentColor, + 0.2f*iPlusOne, 0.3f*iPlusOne, 0.1f*iPlusOne, 0.5); + float yPos = 150 * (float)i; + rsgDrawRect(150, yPos, 350, yPos + 200, 0); + } + + rsgBindProgramStore(gProgStoreBlendAdd); + for (i = 0; i < 3; i ++) { + float iPlusOne = (float)(i + 1); + rsgProgramFragmentConstantColor(gProgFragmentColor, + 0.3f*iPlusOne, 0.1f*iPlusOne, 0.2f*iPlusOne, 0.5); + float yPos = 150 * (float)i; + rsgDrawRect(300, yPos, 500, yPos + 200, 0); + } + + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("No Blending", 10, 50); + rsgDrawText("Alpha Blending", 160, 150); + rsgDrawText("Additive Blending", 320, 250); + +} + +static void displayMeshSamples() { + + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadTranslate(&matrix, 128, 128, 0); + rsgProgramVertexLoadModelMatrix(&matrix); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNone); + rsgBindProgramFragment(gProgFragmentTexture); + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); + + rsgDrawMesh(gMbyNMesh); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("User gen 10 by 10 grid mesh", 10, 250); +} + +static void displayTextureSamplers() { + + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNone); + rsgBindProgramFragment(gProgFragmentTexture); + rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); + + // Linear clamp + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + float startX = 0, startY = 0; + float width = 300, height = 300; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1.1, + startX + width, startY + height, 0, 1.1, 1.1, + startX + width, startY, 0, 1.1, 0); + + // Linear Wrap + rsgBindSampler(gProgFragmentTexture, 0, gLinearWrap); + startX = 0; startY = 300; + width = 300; height = 300; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1.1, + startX + width, startY + height, 0, 1.1, 1.1, + startX + width, startY, 0, 1.1, 0); + + // Nearest + rsgBindSampler(gProgFragmentTexture, 0, gNearestClamp); + startX = 300; startY = 0; + width = 300; height = 300; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1.1, + startX + width, startY + height, 0, 1.1, 1.1, + startX + width, startY, 0, 1.1, 0); + + rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap); + startX = 300; startY = 300; + width = 300; height = 300; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1.5, + startX + width, startY + height, 0, 1.5, 1.5, + startX + width, startY, 0, 1.5, 0); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Filtering: linear clamp", 10, 290); + rsgDrawText("Filtering: linear wrap", 10, 590); + rsgDrawText("Filtering: nearest clamp", 310, 290); + rsgDrawText("Filtering: miplinear wrap", 310, 590); +} + +static float gTorusRotation = 0; + +static void displayCullingSamples() { + rsgBindProgramVertex(gProgVertex); + // Setup the projectioni matrix with 60 degree field of view + rs_matrix4x4 proj; + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNoneDepth); + rsgBindProgramFragment(gProgFragmentTexture); + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + rsgBindTexture(gProgFragmentTexture, 0, gTexTorus); + + // Aplly a rotation to our mesh + gTorusRotation += 50.0f * gDt; + if (gTorusRotation > 360.0f) { + gTorusRotation -= 360.0f; + } + + rs_matrix4x4 matrix; + // Position our model on the screen + rsMatrixLoadTranslate(&matrix, -2.0f, 0.0f, -10.0f); + rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f); + rsgProgramVertexLoadModelMatrix(&matrix); + // Use front face culling + rsgBindProgramRaster(gCullFront); + rsgDrawMesh(gTorusMesh); + + rsMatrixLoadTranslate(&matrix, 2.0f, 0.0f, -10.0f); + rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f); + rsgProgramVertexLoadModelMatrix(&matrix); + // Use back face culling + rsgBindProgramRaster(gCullBack); + rsgDrawMesh(gTorusMesh); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Displaying mesh front/back face culling", 10, rsgGetHeight() - 10); +} + +static float gLight0Rotation = 0; +static float gLight1Rotation = 0; + +static void setupCustomShaderLights() { + float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f}; + float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f}; + float4 light0DiffCol = {0.9f, 0.7f, 0.7f, 1.0f}; + float4 light0SpecCol = {0.9f, 0.6f, 0.6f, 1.0f}; + float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f}; + float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f}; + + gLight0Rotation += 50.0f * gDt; + if (gLight0Rotation > 360.0f) { + gLight0Rotation -= 360.0f; + } + gLight1Rotation -= 50.0f * gDt; + if (gLight1Rotation > 360.0f) { + gLight1Rotation -= 360.0f; + } + + rs_matrix4x4 l0Mat; + rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f); + light0Pos = rsMatrixMultiply(&l0Mat, light0Pos); + rs_matrix4x4 l1Mat; + rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f); + light1Pos = rsMatrixMultiply(&l1Mat, light1Pos); + + // Set light 0 properties + gVSConstants->light0_Posision = light0Pos; + gVSConstants->light0_Diffuse = 1.0f; + gVSConstants->light0_Specular = 0.5f; + gVSConstants->light0_CosinePower = 10.0f; + // Set light 1 properties + gVSConstants->light1_Posision = light1Pos; + gVSConstants->light1_Diffuse = 1.0f; + gVSConstants->light1_Specular = 0.7f; + gVSConstants->light1_CosinePower = 25.0f; + rsAllocationMarkDirty(rsGetAllocation(gVSConstants)); + + gVSConstants2->light_Posision[0] = light0Pos; + gVSConstants2->light_Diffuse[0] = 1.0f; + gVSConstants2->light_Specular[0] = 0.5f; + gVSConstants2->light_CosinePower[0] = 10.0f; + gVSConstants2->light_Posision[1] = light1Pos; + gVSConstants2->light_Diffuse[1] = 1.0f; + gVSConstants2->light_Specular[1] = 0.7f; + gVSConstants2->light_CosinePower[1] = 25.0f; + rsAllocationMarkDirty(rsGetAllocation(gVSConstants2)); + + // Update fragmetn shader constants + // Set light 0 colors + gFSConstants->light0_DiffuseColor = light0DiffCol; + gFSConstants->light0_SpecularColor = light0SpecCol; + // Set light 1 colors + gFSConstants->light1_DiffuseColor = light1DiffCol; + gFSConstants->light1_SpecularColor = light1SpecCol; + rsAllocationMarkDirty(rsGetAllocation(gFSConstants)); + + gFSConstants2->light_DiffuseColor[0] = light0DiffCol; + gFSConstants2->light_SpecularColor[0] = light0SpecCol; + // Set light 1 colors + gFSConstants2->light_DiffuseColor[1] = light1DiffCol; + gFSConstants2->light_SpecularColor[1] = light1SpecCol; + rsAllocationMarkDirty(rsGetAllocation(gFSConstants2)); +} + +static void displayCustomShaderSamples() { + + // Update vertex shader constants + // Load model matrix + // Aplly a rotation to our mesh + gTorusRotation += 50.0f * gDt; + if (gTorusRotation > 360.0f) { + gTorusRotation -= 360.0f; + } + + // Position our model on the screen + rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f); + rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f); + // Setup the projectioni matrix + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f); + setupCustomShaderLights(); + + rsgBindProgramVertex(gProgVertexCustom); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNoneDepth); + rsgBindProgramFragment(gProgFragmentCustom); + rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp); + rsgBindTexture(gProgFragmentCustom, 0, gTexTorus); + + // Use back face culling + rsgBindProgramRaster(gCullBack); + rsgDrawMesh(gTorusMesh); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Custom shader sample", 10, rsgGetHeight() - 10); +} + +static void displayCustomShaderSamples2() { + + // Update vertex shader constants + // Load model matrix + // Aplly a rotation to our mesh + gTorusRotation += 50.0f * gDt; + if (gTorusRotation > 360.0f) { + gTorusRotation -= 360.0f; + } + + // Position our model on the screen + rsMatrixLoadTranslate(&gVSConstants2->model[1], 0.0f, 0.0f, -10.0f); + rsMatrixLoadIdentity(&gVSConstants2->model[0]); + rsMatrixRotate(&gVSConstants2->model[0], gTorusRotation, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&gVSConstants2->model[0], gTorusRotation, 0.0f, 0.0f, 1.0f); + // Setup the projectioni matrix + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&gVSConstants2->proj, 30.0f, aspect, 0.1f, 100.0f); + setupCustomShaderLights(); + + rsgBindProgramVertex(gProgVertexCustom2); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNoneDepth); + rsgBindProgramFragment(gProgFragmentCustom2); + rsgBindSampler(gProgFragmentCustom2, 0, gLinearClamp); + rsgBindTexture(gProgFragmentCustom2, 0, gTexTorus); + + // Use back face culling + rsgBindProgramRaster(gCullBack); + rsgDrawMesh(gTorusMesh); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Custom shader sample with array uniforms", 10, rsgGetHeight() - 10); +} + +static void displayCubemapShaderSample() { + // Update vertex shader constants + // Load model matrix + // Aplly a rotation to our mesh + gTorusRotation += 50.0f * gDt; + if (gTorusRotation > 360.0f) { + gTorusRotation -= 360.0f; + } + + // Position our model on the screen + // Position our model on the screen + rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f); + rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f); + // Setup the projectioni matrix + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f); + rsAllocationMarkDirty(rsGetAllocation(gFSConstants)); + + rsgBindProgramVertex(gProgVertexCube); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNoneDepth); + rsgBindProgramFragment(gProgFragmentCube); + rsgBindSampler(gProgFragmentCube, 0, gLinearClamp); + rsgBindTexture(gProgFragmentCube, 0, gTexCube); + + // Use back face culling + rsgBindProgramRaster(gCullBack); + rsgDrawMesh(gTorusMesh); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Cubemap shader sample", 10, rsgGetHeight() - 10); +} + +static void displayMultitextureSample() { + bindProgramVertexOrtho(); + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNone); + rsgBindProgramFragment(gProgFragmentMultitex); + rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp); + rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap); + rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp); + rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker); + rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus); + rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent); + + float startX = 0, startY = 0; + float width = 256, height = 256; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 1, + startX + width, startY + height, 0, 1, 1, + startX + width, startY, 0, 1, 0); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + rsgDrawText("Custom shader with multitexturing", 10, 280); +} + +static float gAnisoTime = 0.0f; +static uint anisoMode = 0; +static void displayAnisoSample() { + + gAnisoTime += gDt; + + rsgBindProgramVertex(gProgVertex); + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rs_matrix4x4 proj; + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + rs_matrix4x4 matrix; + // Fragment shader with texture + rsgBindProgramStore(gProgStoreBlendNone); + rsgBindProgramFragment(gProgFragmentTexture); + rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, -10.0f); + rsMatrixRotate(&matrix, -80, 1.0f, 0.0f, 0.0f); + rsgProgramVertexLoadModelMatrix(&matrix); + + rsgBindProgramRaster(gCullNone); + + rsgBindTexture(gProgFragmentTexture, 0, gTexChecker); + + if (gAnisoTime >= 5.0f) { + gAnisoTime = 0.0f; + anisoMode ++; + anisoMode = anisoMode % 3; + } + + if (anisoMode == 0) { + rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso8); + } else if (anisoMode == 1) { + rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso15); + } else { + rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap); + } + + float startX = -15; + float startY = -15; + float width = 30; + float height = 30; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, + startX, startY + height, 0, 0, 10, + startX + width, startY + height, 0, 10, 10, + startX + width, startY, 0, 10, 0); + + rsgBindProgramRaster(gCullBack); + + rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgBindFont(gFontMono); + if (anisoMode == 0) { + rsgDrawText("Anisotropic filtering 8", 10, 40); + } else if (anisoMode == 1) { + rsgDrawText("Anisotropic filtering 15", 10, 40); + } else { + rsgDrawText("Miplinear filtering", 10, 40); + } +} + +int root(int launchID) { + + gDt = rsGetDt(); + + rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); + rsgClearDepth(1.0f); + + switch (gDisplayMode) { + case 0: + displayFontSamples(); + break; + case 1: + displayShaderSamples(); + break; + case 2: + displayBlendingSamples(); + break; + case 3: + displayMeshSamples(); + break; + case 4: + displayTextureSamplers(); + break; + case 5: + displayCullingSamples(); + break; + case 6: + displayCustomShaderSamples(); + break; + case 7: + displayMultitextureSample(); + break; + case 8: + displayAnisoSample(); + break; + case 9: + displayCustomShaderSamples2(); + break; + case 10: + displayCubemapShaderSample(); + break; + } + + return 10; +} diff --git a/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh b/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh new file mode 100644 index 0000000..1d804c6 --- /dev/null +++ b/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh @@ -0,0 +1,83 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.samples) + +typedef struct VertexShaderConstants_s { + rs_matrix4x4 model; + rs_matrix4x4 proj; + float4 light0_Posision; + float light0_Diffuse; + float light0_Specular; + float light0_CosinePower; + + float4 light1_Posision; + float light1_Diffuse; + float light1_Specular; + float light1_CosinePower; +} VertexShaderConstants; + +typedef struct VertexShaderConstants2_s { + rs_matrix4x4 model[2]; + rs_matrix4x4 proj; + float4 light_Posision[2]; + float light_Diffuse[2]; + float light_Specular[2]; + float light_CosinePower[2]; +} VertexShaderConstants2; + +typedef struct VertexShaderConstants3_s { + rs_matrix4x4 model; + rs_matrix4x4 proj; + float time; +} VertexShaderConstants3; + + +typedef struct FragentShaderConstants_s { + float4 light0_DiffuseColor; + float4 light0_SpecularColor; + + float4 light1_DiffuseColor; + float4 light1_SpecularColor; +} FragentShaderConstants; + +typedef struct FragentShaderConstants2_s { + float4 light_DiffuseColor[2]; + float4 light_SpecularColor[2]; +} FragentShaderConstants2; + +typedef struct FragentShaderConstants3_s { + float4 light0_DiffuseColor; + float4 light0_SpecularColor; + float4 light0_Posision; + float light0_Diffuse; + float light0_Specular; + float light0_CosinePower; + + float4 light1_DiffuseColor; + float4 light1_SpecularColor; + float4 light1_Posision; + float light1_Diffuse; + float light1_Specular; + float light1_CosinePower; +} FragentShaderConstants3; + +typedef struct VertexShaderInputs_s { + float4 position; + float3 normal; + float2 texture0; +} VertexShaderInputs; + diff --git a/libs/rs/java/tests/Android.mk b/libs/rs/java/tests/Android.mk new file mode 100644 index 0000000..6c992d5 --- /dev/null +++ b/libs/rs/java/tests/Android.mk @@ -0,0 +1,30 @@ +# +# Copyright (C) 2008 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. +# + +ifneq ($(TARGET_SIMULATOR),true) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) + +LOCAL_PACKAGE_NAME := RSTest + +include $(BUILD_PACKAGE) + +endif diff --git a/libs/rs/java/tests/AndroidManifest.xml b/libs/rs/java/tests/AndroidManifest.xml new file mode 100644 index 0000000..b660398 --- /dev/null +++ b/libs/rs/java/tests/AndroidManifest.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.rs.test"> + <application + android:label="_RS_Test" + android:icon="@drawable/test_pattern"> + <activity android:name="RSTest" + android:screenOrientation="portrait"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/libs/rs/java/tests/res/drawable/test_pattern.png b/libs/rs/java/tests/res/drawable/test_pattern.png Binary files differnew file mode 100644 index 0000000..e7d1455 --- /dev/null +++ b/libs/rs/java/tests/res/drawable/test_pattern.png diff --git a/libs/rs/java/Film/src/com/android/film/Film.java b/libs/rs/java/tests/src/com/android/rs/test/RSTest.java index 6e99816..6b8fa6b 100644 --- a/libs/rs/java/Film/src/com/android/film/Film.java +++ b/libs/rs/java/tests/src/com/android/rs/test/RSTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.film; +package com.android.rs.test; import android.renderscript.RSSurfaceView; import android.renderscript.RenderScript; @@ -37,48 +37,43 @@ import android.widget.ListView; import java.lang.Runtime; -public class Film extends Activity { +public class RSTest extends Activity { //EventListener mListener = new EventListener(); private static final String LOG_TAG = "libRS_jni"; private static final boolean DEBUG = false; private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; - private FilmView mView; + private RSTestView mView; // get the current looper (from your Activity UI thread for instance - - @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); // Create our Preview view and set it as the content of our // Activity - mView = new FilmView(this); + mView = new RSTestView(this); setContentView(mView); } @Override protected void onResume() { // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity looses focus + // to take appropriate action when the activity loses focus super.onResume(); - mView.onResume(); + mView.resume(); } @Override protected void onPause() { // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity looses focus + // to take appropriate action when the activity loses focus super.onPause(); - mView.onPause(); - - Runtime.getRuntime().exit(0); + mView.pause(); } - static void log(String message) { if (LOG_ENABLED) { Log.v(LOG_TAG, message); @@ -87,4 +82,3 @@ public class Film extends Activity { } - diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java new file mode 100644 index 0000000..541bf22 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; +import android.util.Log; +import java.util.ArrayList; +import java.util.ListIterator; +import java.util.Timer; +import java.util.TimerTask; + + +public class RSTestCore { + int mWidth; + int mHeight; + Context mCtx; + + public RSTestCore(Context ctx) { + mCtx = ctx; + } + + private Resources mRes; + private RenderScriptGL mRS; + + private Font mFont; + ScriptField_ListAllocs_s mListAllocs; + int mLastX; + int mLastY; + private ScriptC_rslist mScript; + + private ArrayList<UnitTest> unitTests; + private ListIterator<UnitTest> test_iter; + private UnitTest activeTest; + private boolean stopTesting; + + /* Periodic timer for ensuring future tests get scheduled */ + private Timer mTimer; + public static final int RS_TIMER_PERIOD = 100; + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + stopTesting = false; + + mScript = new ScriptC_rslist(mRS, mRes, R.raw.rslist); + + unitTests = new ArrayList<UnitTest>(); + + unitTests.add(new UT_primitives(this, mRes, mCtx)); + unitTests.add(new UT_rsdebug(this, mRes, mCtx)); + unitTests.add(new UT_rstime(this, mRes, mCtx)); + unitTests.add(new UT_rstypes(this, mRes, mCtx)); + unitTests.add(new UT_math(this, mRes, mCtx)); + unitTests.add(new UT_fp_mad(this, mRes, mCtx)); + /* + unitTests.add(new UnitTest(null, "<Pass>", 1)); + unitTests.add(new UnitTest()); + unitTests.add(new UnitTest(null, "<Fail>", -1)); + + for (int i = 0; i < 20; i++) { + unitTests.add(new UnitTest(null, "<Pass>", 1)); + } + */ + + UnitTest [] uta = new UnitTest[unitTests.size()]; + uta = unitTests.toArray(uta); + + mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length); + for (int i = 0; i < uta.length; i++) { + ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item(); + listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT); + listElem.result = uta[i].result; + mListAllocs.set(listElem, i, false); + uta[i].setItem(listElem); + } + + mListAllocs.copyAll(); + + mScript.bind_gList(mListAllocs); + + mFont = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8); + mScript.set_gFont(mFont); + + mRS.bindRootScript(mScript); + + test_iter = unitTests.listIterator(); + refreshTestResults(); /* Kick off the first test */ + + TimerTask pTask = new TimerTask() { + public void run() { + refreshTestResults(); + } + }; + + mTimer = new Timer(); + mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD); + } + + public void checkAndRunNextTest() { + if (activeTest != null) { + if (!activeTest.isAlive()) { + /* Properly clean up on our last test */ + try { + activeTest.join(); + } + catch (InterruptedException e) { + } + activeTest = null; + } + } + + if (!stopTesting && activeTest == null) { + if (test_iter.hasNext()) { + activeTest = test_iter.next(); + activeTest.start(); + /* This routine will only get called once when a new test + * should start running. The message handler in UnitTest.java + * ensures this. */ + } + else { + if (mTimer != null) { + mTimer.cancel(); + mTimer.purge(); + mTimer = null; + } + } + } + } + + public void refreshTestResults() { + checkAndRunNextTest(); + + if (mListAllocs != null && mScript != null && mRS != null) { + mListAllocs.copyAll(); + + mScript.bind_gList(mListAllocs); + mRS.bindRootScript(mScript); + } + } + + public void cleanup() { + stopTesting = true; + UnitTest t = activeTest; + + /* Stop periodic refresh of testing */ + if (mTimer != null) { + mTimer.cancel(); + mTimer.purge(); + mTimer = null; + } + + /* Wait to exit until we finish the current test */ + if (t != null) { + try { + t.join(); + } + catch (InterruptedException e) { + } + t = null; + } + + } + + public void newTouchPosition(float x, float y, float pressure, int id) { + } + + public void onActionDown(int x, int y) { + mScript.set_gDY(0.0f); + mLastX = x; + mLastY = y; + refreshTestResults(); + } + + public void onActionMove(int x, int y) { + int dx = mLastX - x; + int dy = mLastY - y; + + if (Math.abs(dy) <= 2) { + dy = 0; + } + + mScript.set_gDY(dy); + + mLastX = x; + mLastY = y; + refreshTestResults(); + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java new file mode 100644 index 0000000..368f286 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.rs.test; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class RSTestView extends RSSurfaceView { + + private Context mCtx; + + public RSTestView(Context context) { + super(context); + mCtx = context; + //setFocusable(true); + } + + private RenderScriptGL mRS; + private RSTestCore mRender; + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); + mRender = new RSTestCore(mCtx); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if(mRS != null) { + mRender.cleanup(); + mRS = null; + destroyRenderScriptGL(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) + { + boolean ret = false; + int act = ev.getAction(); + if (act == ev.ACTION_DOWN) { + mRender.onActionDown((int)ev.getX(), (int)ev.getY()); + ret = true; + } + else if (act == ev.ACTION_MOVE) { + mRender.onActionMove((int)ev.getX(), (int)ev.getY()); + ret = true; + } + + return ret; + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_fp_mad.java b/libs/rs/java/tests/src/com/android/rs/test/UT_fp_mad.java new file mode 100644 index 0000000..f2c91af --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/UT_fp_mad.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; + +public class UT_fp_mad extends UnitTest { + private Resources mRes; + + protected UT_fp_mad(RSTestCore rstc, Resources res, Context ctx) { + super(rstc, "Fp_Mad", ctx); + mRes = res; + } + + public void run() { + RenderScript pRS = RenderScript.create(mCtx); + ScriptC_fp_mad s = new ScriptC_fp_mad(pRS, mRes, R.raw.fp_mad); + pRS.setMessageHandler(mRsMessage); + s.invoke_fp_mad_test(0, 0); + pRS.finish(); + waitForMessage(); + pRS.destroy(); + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_math.java b/libs/rs/java/tests/src/com/android/rs/test/UT_math.java new file mode 100644 index 0000000..bf133be --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/UT_math.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; + +public class UT_math extends UnitTest { + private Resources mRes; + + protected UT_math(RSTestCore rstc, Resources res, Context ctx) { + super(rstc, "Math", ctx); + mRes = res; + } + + public void run() { + RenderScript pRS = RenderScript.create(mCtx); + ScriptC_math s = new ScriptC_math(pRS, mRes, R.raw.math); + pRS.setMessageHandler(mRsMessage); + s.invoke_math_test(0, 0); + pRS.finish(); + waitForMessage(); + pRS.destroy(); + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_primitives.java b/libs/rs/java/tests/src/com/android/rs/test/UT_primitives.java new file mode 100644 index 0000000..b7a65a5 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/UT_primitives.java @@ -0,0 +1,104 @@ +/* + * 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. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; + +public class UT_primitives extends UnitTest { + private Resources mRes; + + protected UT_primitives(RSTestCore rstc, Resources res, Context ctx) { + super(rstc, "Primitives", ctx); + mRes = res; + } + + private boolean initializeGlobals(ScriptC_primitives s) { + float pF = s.get_floatTest(); + if (pF != 1.99f) { + return false; + } + s.set_floatTest(2.99f); + + double pD = s.get_doubleTest(); + if (pD != 2.05) { + return false; + } + s.set_doubleTest(3.05); + + byte pC = s.get_charTest(); + if (pC != -8) { + return false; + } + s.set_charTest((byte)-16); + + short pS = s.get_shortTest(); + if (pS != -16) { + return false; + } + s.set_shortTest((short)-32); + + int pI = s.get_intTest(); + if (pI != -32) { + return false; + } + s.set_intTest(-64); + + long pL = s.get_longTest(); + if (pL != 17179869184l) { + return false; + } + s.set_longTest(17179869185l); + + long puL = s.get_ulongTest(); + if (puL != 4611686018427387904L) { + return false; + } + s.set_ulongTest(4611686018427387903L); + + + long pLL = s.get_longlongTest(); + if (pLL != 68719476736L) { + return false; + } + s.set_longlongTest(68719476735L); + + long pu64 = s.get_uint64_tTest(); + if (pu64 != 117179869184l) { + return false; + } + s.set_uint64_tTest(117179869185l); + + return true; + } + + public void run() { + RenderScript pRS = RenderScript.create(mCtx); + ScriptC_primitives s = new ScriptC_primitives(pRS, mRes, R.raw.primitives); + pRS.setMessageHandler(mRsMessage); + if (!initializeGlobals(s)) { + // initializeGlobals failed + result = -1; + } else { + s.invoke_primitives_test(0, 0); + pRS.finish(); + waitForMessage(); + } + pRS.destroy(); + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_rsdebug.java b/libs/rs/java/tests/src/com/android/rs/test/UT_rsdebug.java new file mode 100644 index 0000000..0614b1a --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/UT_rsdebug.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; + +public class UT_rsdebug extends UnitTest { + private Resources mRes; + + protected UT_rsdebug(RSTestCore rstc, Resources res, Context ctx) { + super(rstc, "rsDebug", ctx); + mRes = res; + } + + public void run() { + RenderScript pRS = RenderScript.create(mCtx); + ScriptC_rsdebug s = new ScriptC_rsdebug(pRS, mRes, R.raw.rsdebug); + pRS.setMessageHandler(mRsMessage); + s.invoke_test_rsdebug(0, 0); + pRS.finish(); + waitForMessage(); + pRS.destroy(); + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java new file mode 100644 index 0000000..f302e1a --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; + +public class UT_rstime extends UnitTest { + private Resources mRes; + + protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) { + super(rstc, "rsTime", ctx); + mRes = res; + } + + public void run() { + RenderScript pRS = RenderScript.create(mCtx); + ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime); + pRS.setMessageHandler(mRsMessage); + s.invoke_test_rstime(0, 0); + pRS.finish(); + waitForMessage(); + pRS.destroy(); + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_rstypes.java b/libs/rs/java/tests/src/com/android/rs/test/UT_rstypes.java new file mode 100644 index 0000000..74211c8 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/UT_rstypes.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; + +public class UT_rstypes extends UnitTest { + private Resources mRes; + + protected UT_rstypes(RSTestCore rstc, Resources res, Context ctx) { + super(rstc, "rsTypes", ctx); + mRes = res; + } + + public void run() { + RenderScript pRS = RenderScript.create(mCtx); + ScriptC_rstypes s = new ScriptC_rstypes(pRS, mRes, R.raw.rstypes); + pRS.setMessageHandler(mRsMessage); + s.invoke_test_rstypes(0, 0); + pRS.finish(); + waitForMessage(); + pRS.destroy(); + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java b/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java new file mode 100644 index 0000000..a7722c7 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package com.android.rs.test; +import android.content.Context; +import android.renderscript.RenderScript.RSMessageHandler; +import android.util.Log; + +public class UnitTest extends Thread { + public String name; + public int result; + private ScriptField_ListAllocs_s.Item mItem; + private RSTestCore mRSTC; + private boolean msgHandled; + protected Context mCtx; + + /* These constants must match those in shared.rsh */ + public static final int RS_MSG_TEST_PASSED = 100; + public static final int RS_MSG_TEST_FAILED = 101; + + private static int numTests = 0; + public int testID; + + protected UnitTest(RSTestCore rstc, String n, int initResult, Context ctx) { + super(); + mRSTC = rstc; + name = n; + msgHandled = false; + mCtx = ctx; + result = initResult; + testID = numTests++; + } + + protected UnitTest(RSTestCore rstc, String n, Context ctx) { + this(rstc, n, 0, ctx); + } + + protected UnitTest(RSTestCore rstc, Context ctx) { + this (rstc, "<Unknown>", ctx); + } + + protected UnitTest(Context ctx) { + this (null, ctx); + } + + protected RSMessageHandler mRsMessage = new RSMessageHandler() { + public void run() { + if (result == 0) { + switch (mID) { + case RS_MSG_TEST_PASSED: + result = 1; + break; + case RS_MSG_TEST_FAILED: + result = -1; + break; + default: + android.util.Log.v("RenderScript", "Unit test got unexpected message"); + return; + } + } + + if (mItem != null) { + mItem.result = result; + msgHandled = true; + try { + mRSTC.refreshTestResults(); + } + catch (IllegalStateException e) { + /* Ignore the case where our message receiver has been + disconnected. This happens when we leave the application + before it finishes running all of the unit tests. */ + } + } + } + }; + + public void waitForMessage() { + while (!msgHandled) { + yield(); + } + } + + public void setItem(ScriptField_ListAllocs_s.Item item) { + mItem = item; + } + + public void run() { + /* This method needs to be implemented for each subclass */ + if (mRSTC != null) { + mRSTC.refreshTestResults(); + } + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs new file mode 100644 index 0000000..b6f2b2a --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs @@ -0,0 +1,174 @@ +#include "shared.rsh" + +const int TEST_COUNT = 1; + +static float data_f1[1025]; +static float4 data_f4[1025]; + +static void test_mad4(uint32_t index) { + start(); + + float total = 0; + // Do ~1 billion ops + for (int ct=0; ct < 1000 * (1000 / 80); ct++) { + for (int i=0; i < (1000); i++) { + data_f4[i] = (data_f4[i] * 0.02f + + data_f4[i+1] * 0.04f + + data_f4[i+2] * 0.05f + + data_f4[i+3] * 0.1f + + data_f4[i+4] * 0.2f + + data_f4[i+5] * 0.2f + + data_f4[i+6] * 0.1f + + data_f4[i+7] * 0.05f + + data_f4[i+8] * 0.04f + + data_f4[i+9] * 0.02f + 1.f); + } + } + + float time = end(index); + rsDebug("fp_mad4 M ops", 1000.f / time); +} + +static void test_mad(uint32_t index) { + start(); + + float total = 0; + // Do ~1 billion ops + for (int ct=0; ct < 1000 * (1000 / 20); ct++) { + for (int i=0; i < (1000); i++) { + data_f1[i] = (data_f1[i] * 0.02f + + data_f1[i+1] * 0.04f + + data_f1[i+2] * 0.05f + + data_f1[i+3] * 0.1f + + data_f1[i+4] * 0.2f + + data_f1[i+5] * 0.2f + + data_f1[i+6] * 0.1f + + data_f1[i+7] * 0.05f + + data_f1[i+8] * 0.04f + + data_f1[i+9] * 0.02f + 1.f); + } + } + + float time = end(index); + rsDebug("fp_mad M ops", 1000.f / time); +} + +static void test_norm(uint32_t index) { + start(); + + float total = 0; + // Do ~10 M ops + for (int ct=0; ct < 1000 * 10; ct++) { + for (int i=0; i < (1000); i++) { + data_f4[i] = normalize(data_f4[i]); + } + } + + float time = end(index); + rsDebug("fp_norm M ops", 10.f / time); +} + +static void test_sincos4(uint32_t index) { + start(); + + float total = 0; + // Do ~10 M ops + for (int ct=0; ct < 1000 * 10 / 4; ct++) { + for (int i=0; i < (1000); i++) { + data_f4[i] = sin(data_f4[i]) * cos(data_f4[i]); + } + } + + float time = end(index); + rsDebug("fp_sincos4 M ops", 10.f / time); +} + +static void test_sincos(uint32_t index) { + start(); + + float total = 0; + // Do ~10 M ops + for (int ct=0; ct < 1000 * 10; ct++) { + for (int i=0; i < (1000); i++) { + data_f1[i] = sin(data_f1[i]) * cos(data_f1[i]); + } + } + + float time = end(index); + rsDebug("fp_sincos M ops", 10.f / time); +} + +static void test_clamp(uint32_t index) { + start(); + + // Do ~100 M ops + for (int ct=0; ct < 1000 * 100; ct++) { + for (int i=0; i < (1000); i++) { + data_f1[i] = clamp(data_f1[i], -1.f, 1.f); + } + } + + float time = end(index); + rsDebug("fp_clamp M ops", 100.f / time); + + start(); + // Do ~100 M ops + for (int ct=0; ct < 1000 * 100; ct++) { + for (int i=0; i < (1000); i++) { + if (data_f1[i] < -1.f) data_f1[i] = -1.f; + if (data_f1[i] > -1.f) data_f1[i] = 1.f; + } + } + + time = end(index); + rsDebug("fp_clamp ref M ops", 100.f / time); +} + +static void test_clamp4(uint32_t index) { + start(); + + float total = 0; + // Do ~100 M ops + for (int ct=0; ct < 1000 * 100 /4; ct++) { + for (int i=0; i < (1000); i++) { + data_f4[i] = clamp(data_f4[i], -1.f, 1.f); + } + } + + float time = end(index); + rsDebug("fp_clamp4 M ops", 100.f / time); +} + +void fp_mad_test(uint32_t index, int test_num) { + int x; + for (x=0; x < 1025; x++) { + data_f1[x] = (x & 0xf) * 0.1f; + data_f4[x].x = (x & 0xf) * 0.1f; + data_f4[x].y = (x & 0xf0) * 0.1f; + data_f4[x].z = (x & 0x33) * 0.1f; + data_f4[x].w = (x & 0x77) * 0.1f; + } + + test_mad4(index); + test_mad(index); + + for (x=0; x < 1025; x++) { + data_f1[x] = (x & 0xf) * 0.1f + 1.f; + data_f4[x].x = (x & 0xf) * 0.1f + 1.f; + data_f4[x].y = (x & 0xf0) * 0.1f + 1.f; + data_f4[x].z = (x & 0x33) * 0.1f + 1.f; + data_f4[x].w = (x & 0x77) * 0.1f + 1.f; + } + + test_norm(index); + test_sincos4(index); + test_sincos(index); + test_clamp4(index); + test_clamp(index); + + // TODO Actually verify test result accuracy + rsDebug("fp_mad_test PASSED", 0); + rsSendToClientBlocking(RS_MSG_TEST_PASSED); +} + + diff --git a/libs/rs/java/tests/src/com/android/rs/test/math.rs b/libs/rs/java/tests/src/com/android/rs/test/math.rs new file mode 100644 index 0000000..8cad82b --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/math.rs @@ -0,0 +1,322 @@ +#include "shared.rsh" + +// Testing math library + +volatile float f1; +volatile float2 f2; +volatile float3 f3; +volatile float4 f4; + +volatile int i1; +volatile int2 i2; +volatile int3 i3; +volatile int4 i4; + +volatile uint ui1; +volatile uint2 ui2; +volatile uint3 ui3; +volatile uint4 ui4; + +volatile short s1; +volatile short2 s2; +volatile short3 s3; +volatile short4 s4; + +volatile ushort us1; +volatile ushort2 us2; +volatile ushort3 us3; +volatile ushort4 us4; + +volatile char c1; +volatile char2 c2; +volatile char3 c3; +volatile char4 c4; + +volatile uchar uc1; +volatile uchar2 uc2; +volatile uchar3 uc3; +volatile uchar4 uc4; + +#define TEST_FN_FUNC_FN(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1); \ + f2 = fnc(f2); \ + f3 = fnc(f3); \ + f4 = fnc(f4); + +#define TEST_FN_FUNC_FN_PFN(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1, (float*) &f1); \ + f2 = fnc(f2, (float2*) &f2); \ + f3 = fnc(f3, (float3*) &f3); \ + f4 = fnc(f4, (float4*) &f4); + +#define TEST_FN_FUNC_FN_FN(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1, f1); \ + f2 = fnc(f2, f2); \ + f3 = fnc(f3, f3); \ + f4 = fnc(f4, f4); + +#define TEST_FN_FUNC_FN_F(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1, f1); \ + f2 = fnc(f2, f1); \ + f3 = fnc(f3, f1); \ + f4 = fnc(f4, f1); + +#define TEST_FN_FUNC_FN_IN(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1, i1); \ + f2 = fnc(f2, i2); \ + f3 = fnc(f3, i3); \ + f4 = fnc(f4, i4); + +#define TEST_FN_FUNC_FN_I(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1, i1); \ + f2 = fnc(f2, i1); \ + f3 = fnc(f3, i1); \ + f4 = fnc(f4, i1); + +#define TEST_FN_FUNC_FN_FN_FN(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1, f1, f1); \ + f2 = fnc(f2, f2, f2); \ + f3 = fnc(f3, f3, f3); \ + f4 = fnc(f4, f4, f4); + +#define TEST_FN_FUNC_FN_PIN(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1, (int*) &i1); \ + f2 = fnc(f2, (int2*) &i2); \ + f3 = fnc(f3, (int3*) &i3); \ + f4 = fnc(f4, (int4*) &i4); + +#define TEST_FN_FUNC_FN_FN_PIN(fnc) \ + rsDebug("Testing " #fnc, 0); \ + f1 = fnc(f1, f1, (int*) &i1); \ + f2 = fnc(f2, f2, (int2*) &i2); \ + f3 = fnc(f3, f3, (int3*) &i3); \ + f4 = fnc(f4, f4, (int4*) &i4); + +#define TEST_IN_FUNC_FN(fnc) \ + rsDebug("Testing " #fnc, 0); \ + i1 = fnc(f1); \ + i2 = fnc(f2); \ + i3 = fnc(f3); \ + i4 = fnc(f4); + + +static bool test_fp_math(uint32_t index) { + bool failed = false; + start(); + + TEST_FN_FUNC_FN(acos); + TEST_FN_FUNC_FN(acosh); + TEST_FN_FUNC_FN(acospi); + TEST_FN_FUNC_FN(asin); + TEST_FN_FUNC_FN(asinh); + TEST_FN_FUNC_FN(asinpi); + TEST_FN_FUNC_FN(atan); + TEST_FN_FUNC_FN_FN(atan2); + TEST_FN_FUNC_FN(atanh); + TEST_FN_FUNC_FN(atanpi); + TEST_FN_FUNC_FN_FN(atan2pi); + TEST_FN_FUNC_FN(cbrt); + TEST_FN_FUNC_FN(ceil); + TEST_FN_FUNC_FN_FN(copysign); + TEST_FN_FUNC_FN(cos); + TEST_FN_FUNC_FN(cosh); + TEST_FN_FUNC_FN(cospi); + TEST_FN_FUNC_FN(erfc); + TEST_FN_FUNC_FN(erf); + TEST_FN_FUNC_FN(exp); + TEST_FN_FUNC_FN(exp2); + TEST_FN_FUNC_FN(exp10); + TEST_FN_FUNC_FN(expm1); + TEST_FN_FUNC_FN(fabs); + TEST_FN_FUNC_FN_FN(fdim); + TEST_FN_FUNC_FN(floor); + TEST_FN_FUNC_FN_FN_FN(fma); + TEST_FN_FUNC_FN_FN(fmax); + TEST_FN_FUNC_FN_F(fmax); + TEST_FN_FUNC_FN_FN(fmin); + TEST_FN_FUNC_FN_F(fmin); + TEST_FN_FUNC_FN_FN(fmod); + TEST_FN_FUNC_FN_PFN(fract); + TEST_FN_FUNC_FN_PIN(frexp); + TEST_FN_FUNC_FN_FN(hypot); + TEST_IN_FUNC_FN(ilogb); + TEST_FN_FUNC_FN_IN(ldexp); + TEST_FN_FUNC_FN_I(ldexp); + TEST_FN_FUNC_FN(lgamma); + TEST_FN_FUNC_FN_PIN(lgamma); + TEST_FN_FUNC_FN(log); + TEST_FN_FUNC_FN(log2); + TEST_FN_FUNC_FN(log10); + TEST_FN_FUNC_FN(log1p); + TEST_FN_FUNC_FN(logb); + TEST_FN_FUNC_FN_FN_FN(mad); + TEST_FN_FUNC_FN_PFN(modf); + // nan + TEST_FN_FUNC_FN_FN(nextafter); + TEST_FN_FUNC_FN_FN(pow); + TEST_FN_FUNC_FN_IN(pown); + TEST_FN_FUNC_FN_FN(powr); + TEST_FN_FUNC_FN_FN(remainder); + TEST_FN_FUNC_FN_FN_PIN(remquo); + TEST_FN_FUNC_FN(rint); + TEST_FN_FUNC_FN_IN(rootn); + TEST_FN_FUNC_FN(round); + TEST_FN_FUNC_FN(rsqrt); + TEST_FN_FUNC_FN(sin); + TEST_FN_FUNC_FN_PFN(sincos); + TEST_FN_FUNC_FN(sinh); + TEST_FN_FUNC_FN(sinpi); + TEST_FN_FUNC_FN(sqrt); + TEST_FN_FUNC_FN(tan); + TEST_FN_FUNC_FN(tanh); + TEST_FN_FUNC_FN(tanpi); + TEST_FN_FUNC_FN(tgamma); + TEST_FN_FUNC_FN(trunc); + + float time = end(index); + + if (failed) { + rsDebug("test_fp_math FAILED", time); + } + else { + rsDebug("test_fp_math PASSED", time); + } + + return failed; +} + +#define DECL_INT(prefix) \ +volatile char prefix##_c_1 = 1; \ +volatile char2 prefix##_c_2 = 1; \ +volatile char3 prefix##_c_3 = 1; \ +volatile char4 prefix##_c_4 = 1; \ +volatile uchar prefix##_uc_1 = 1; \ +volatile uchar2 prefix##_uc_2 = 1; \ +volatile uchar3 prefix##_uc_3 = 1; \ +volatile uchar4 prefix##_uc_4 = 1; \ +volatile short prefix##_s_1 = 1; \ +volatile short2 prefix##_s_2 = 1; \ +volatile short3 prefix##_s_3 = 1; \ +volatile short4 prefix##_s_4 = 1; \ +volatile ushort prefix##_us_1 = 1; \ +volatile ushort2 prefix##_us_2 = 1; \ +volatile ushort3 prefix##_us_3 = 1; \ +volatile ushort4 prefix##_us_4 = 1; \ +volatile int prefix##_i_1 = 1; \ +volatile int2 prefix##_i_2 = 1; \ +volatile int3 prefix##_i_3 = 1; \ +volatile int4 prefix##_i_4 = 1; \ +volatile uint prefix##_ui_1 = 1; \ +volatile uint2 prefix##_ui_2 = 1; \ +volatile uint3 prefix##_ui_3 = 1; \ +volatile uint4 prefix##_ui_4 = 1; \ +volatile long prefix##_l_1 = 1; \ +volatile ulong prefix##_ul_1 = 1; + +#define TEST_INT_OP_TYPE(op, type) \ +rsDebug("Testing " #op " for " #type "1", i++); \ +res_##type##_1 = src1_##type##_1 op src2_##type##_1; \ +rsDebug("Testing " #op " for " #type "2", i++); \ +res_##type##_2 = src1_##type##_2 op src2_##type##_2; \ +rsDebug("Testing " #op " for " #type "3", i++); \ +res_##type##_3 = src1_##type##_3 op src2_##type##_3; \ +rsDebug("Testing " #op " for " #type "4", i++); \ +res_##type##_4 = src1_##type##_4 op src2_##type##_4; + +#define TEST_INT_OP(op) \ +TEST_INT_OP_TYPE(op, c) \ +TEST_INT_OP_TYPE(op, uc) \ +TEST_INT_OP_TYPE(op, s) \ +TEST_INT_OP_TYPE(op, us) \ +TEST_INT_OP_TYPE(op, i) \ +TEST_INT_OP_TYPE(op, ui) \ +rsDebug("Testing " #op " for l1", i++); \ +res_l_1 = src1_l_1 op src2_l_1; \ +rsDebug("Testing " #op " for ul1", i++); \ +res_ul_1 = src1_ul_1 op src2_ul_1; + +DECL_INT(res) +DECL_INT(src1) +DECL_INT(src2) + +static bool test_basic_operators() { + bool failed = false; + int i = 0; + + TEST_INT_OP(+); + TEST_INT_OP(-); + TEST_INT_OP(*); + TEST_INT_OP(/); + TEST_INT_OP(%); + TEST_INT_OP(<<); + TEST_INT_OP(>>); + + if (failed) { + rsDebug("test_basic_operators FAILED", 0); + } + else { + rsDebug("test_basic_operators PASSED", 0); + } + + return failed; +} + +#define TEST_CVT(to, from, type) \ +rsDebug("Testing convert from " #from " to " #to, 0); \ +to##1 = from##1; \ +to##2 = convert_##type##2(from##2); \ +to##3 = convert_##type##3(from##3); \ +to##4 = convert_##type##4(from##4); + +#define TEST_CVT_MATRIX(to, type) \ +TEST_CVT(to, c, type); \ +TEST_CVT(to, uc, type); \ +TEST_CVT(to, s, type); \ +TEST_CVT(to, us, type); \ +TEST_CVT(to, i, type); \ +TEST_CVT(to, ui, type); \ +TEST_CVT(to, f, type); \ + +static bool test_convert() { + bool failed = false; + + TEST_CVT_MATRIX(c, char); + TEST_CVT_MATRIX(uc, uchar); + TEST_CVT_MATRIX(s, short); + TEST_CVT_MATRIX(us, ushort); + TEST_CVT_MATRIX(i, int); + TEST_CVT_MATRIX(ui, uint); + TEST_CVT_MATRIX(f, float); + + if (failed) { + rsDebug("test_convert FAILED", 0); + } + else { + rsDebug("test_convert PASSED", 0); + } + + return failed; +} + +void math_test(uint32_t index, int test_num) { + bool failed = false; + failed |= test_convert(); + failed |= test_fp_math(index); + failed |= test_basic_operators(); + + if (failed) { + rsSendToClientBlocking(RS_MSG_TEST_FAILED); + } + else { + rsSendToClientBlocking(RS_MSG_TEST_PASSED); + } +} + diff --git a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs new file mode 100644 index 0000000..ce451da --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs @@ -0,0 +1,61 @@ +#include "shared.rsh" + +// Testing primitive types +float floatTest = 1.99f; +double doubleTest = 2.05; +char charTest = -8; +short shortTest = -16; +int intTest = -32; +long longTest = 17179869184l; // 1 << 34 +long long longlongTest = 68719476736l; // 1 << 36 + +uchar ucharTest = 8; +ushort ushortTest = 16; +uint uintTest = 32; +ulong ulongTest = 4611686018427387904L; +int64_t int64_tTest = -17179869184l; // - 1 << 34 +uint64_t uint64_tTest = 117179869184l; + +static bool test_primitive_types(uint32_t index) { + bool failed = false; + start(); + + _RS_ASSERT(floatTest == 2.99f); + _RS_ASSERT(doubleTest == 3.05); + _RS_ASSERT(charTest == -16); + _RS_ASSERT(shortTest == -32); + _RS_ASSERT(intTest == -64); + _RS_ASSERT(longTest == 17179869185l); + _RS_ASSERT(longlongTest == 68719476735l); + + _RS_ASSERT(ucharTest == 8); + _RS_ASSERT(ushortTest == 16); + _RS_ASSERT(uintTest == 32); + _RS_ASSERT(ulongTest == 4611686018427387903L); + _RS_ASSERT(int64_tTest == -17179869184l); + _RS_ASSERT(uint64_tTest == 117179869185l); + + float time = end(index); + + if (failed) { + rsDebug("test_primitives FAILED", time); + } + else { + rsDebug("test_primitives PASSED", time); + } + + return failed; +} + +void primitives_test(uint32_t index, int test_num) { + bool failed = false; + failed |= test_primitive_types(index); + + if (failed) { + rsSendToClientBlocking(RS_MSG_TEST_FAILED); + } + else { + rsSendToClientBlocking(RS_MSG_TEST_PASSED); + } +} + diff --git a/libs/rs/java/tests/src/com/android/rs/test/rsdebug.rs b/libs/rs/java/tests/src/com/android/rs/test/rsdebug.rs new file mode 100644 index 0000000..f7942a5 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/rsdebug.rs @@ -0,0 +1,56 @@ +#include "shared.rsh" + +// Testing primitive types +float floatTest = 1.99f; +double doubleTest = 2.05; +char charTest = -8; +short shortTest = -16; +int intTest = -32; +long longTest = 17179869184l; // 1 << 34 +long long longlongTest = 68719476736l; // 1 << 36 + +uchar ucharTest = 8; +ushort ushortTest = 16; +uint uintTest = 32; +ulong ulongTest = 4611686018427387904L; +int64_t int64_tTest = -17179869184l; // - 1 << 34 +uint64_t uint64_tTest = 117179869184l; + +static bool basic_test(uint32_t index) { + bool failed = false; + + // This test focuses primarily on compilation-time, not run-time. + // For this reason, none of the outputs are actually checked. + + rsDebug("floatTest", floatTest); + rsDebug("doubleTest", doubleTest); + rsDebug("charTest", charTest); + rsDebug("shortTest", shortTest); + rsDebug("intTest", intTest); + rsDebug("longTest", longTest); + rsDebug("longlongTest", longlongTest); + + rsDebug("ucharTest", ucharTest); + rsDebug("ushortTest", ushortTest); + rsDebug("uintTest", uintTest); + rsDebug("ulongTest", ulongTest); + rsDebug("int64_tTest", int64_tTest); + rsDebug("uint64_tTest", uint64_tTest); + + return failed; +} + +void test_rsdebug(uint32_t index, int test_num) { + bool failed = false; + failed |= basic_test(index); + + if (failed) { + rsSendToClientBlocking(RS_MSG_TEST_FAILED); + rsDebug("rsdebug_test FAILED", -1); + } + else { + rsSendToClientBlocking(RS_MSG_TEST_PASSED); + rsDebug("rsdebug_test PASSED", 0); + } +} + diff --git a/libs/rs/java/tests/src/com/android/rs/test/rslist.rs b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs new file mode 100644 index 0000000..f354a72 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs @@ -0,0 +1,108 @@ +// 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.rs.test) + +#include "rs_graphics.rsh" + +float gDY; + +rs_font gFont; + +typedef struct ListAllocs_s { + rs_allocation text; + int result; +} ListAllocs; + +ListAllocs *gList; + +void init() { + gDY = 0.0f; +} + +int textPos = 0; + +int root(int launchID) { + + rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f); + rsgClearDepth(1.0f); + + textPos -= (int)gDY*2; + gDY *= 0.95; + + rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f); + rsgBindFont(gFont); + color(0.2, 0.2, 0.2, 0); + + rs_allocation listAlloc; + rsSetObject(&listAlloc, rsGetAllocation(gList)); + int allocSize = rsAllocationGetDimX(listAlloc); + + int width = rsgGetWidth(); + int height = rsgGetHeight(); + + int itemHeight = 80; + int totalItemHeight = itemHeight * allocSize; + + /* Prevent scrolling above the top of the list */ + int firstItem = height - totalItemHeight; + if (firstItem < 0) { + firstItem = 0; + } + + /* Prevent scrolling past the last line of the list */ + int lastItem = -1 * (totalItemHeight - height); + if (lastItem > 0) { + lastItem = 0; + } + + if (textPos > firstItem) { + textPos = firstItem; + } + else if (textPos < lastItem) { + textPos = lastItem; + } + + int currentYPos = itemHeight + textPos; + + for(int i = 0; i < allocSize; i ++) { + if(currentYPos - itemHeight > height) { + break; + } + + if(currentYPos > 0) { + switch(gList[i].result) { + case 1: /* Passed */ + rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f); + break; + case -1: /* Failed */ + rsgFontColor(0.9f, 0.5f, 0.5f, 1.0f); + break; + case 0: /* Still Testing */ + rsgFontColor(0.9f, 0.9f, 0.5f, 1.0f); + break; + default: /* Unknown */ + rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f); + break; + } + rsgDrawRect(0, currentYPos - 1, width, currentYPos, 0); + rsgDrawText(gList[i].text, 30, currentYPos - 32); + } + currentYPos += itemHeight; + } + + return 10; +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/rstime.rs b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs new file mode 100644 index 0000000..5e3e078 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs @@ -0,0 +1,52 @@ +#include "shared.rsh" + +static bool basic_test(uint32_t index) { + bool failed = false; + + rs_time_t curTime = rsTime(0); + rs_tm tm; + rsDebug("curTime", curTime); + + rsLocaltime(&tm, &curTime); + + rsDebug("tm.tm_sec", tm.tm_sec); + rsDebug("tm.tm_min", tm.tm_min); + rsDebug("tm.tm_hour", tm.tm_hour); + rsDebug("tm.tm_mday", tm.tm_mday); + rsDebug("tm.tm_mon", tm.tm_mon); + rsDebug("tm.tm_year", tm.tm_year); + rsDebug("tm.tm_wday", tm.tm_wday); + rsDebug("tm.tm_yday", tm.tm_yday); + rsDebug("tm.tm_isdst", tm.tm_isdst); + + // Test a specific time (only valid for PST localtime) + curTime = 1294438893; + rsLocaltime(&tm, &curTime); + + _RS_ASSERT(tm.tm_sec == 33); + _RS_ASSERT(tm.tm_min == 21); + _RS_ASSERT(tm.tm_hour == 14); + _RS_ASSERT(tm.tm_mday == 7); + _RS_ASSERT(tm.tm_mon == 0); + _RS_ASSERT(tm.tm_year == 111); + _RS_ASSERT(tm.tm_wday == 5); + _RS_ASSERT(tm.tm_yday == 6); + _RS_ASSERT(tm.tm_isdst == 0); + + return failed; +} + +void test_rstime(uint32_t index, int test_num) { + bool failed = false; + failed |= basic_test(index); + + if (failed) { + rsSendToClientBlocking(RS_MSG_TEST_FAILED); + rsDebug("rstime_test FAILED", -1); + } + else { + rsSendToClientBlocking(RS_MSG_TEST_PASSED); + rsDebug("rstime_test PASSED", 0); + } +} + diff --git a/libs/rs/java/tests/src/com/android/rs/test/rstypes.rs b/libs/rs/java/tests/src/com/android/rs/test/rstypes.rs new file mode 100644 index 0000000..f3bf244 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/rstypes.rs @@ -0,0 +1,79 @@ +#include "shared.rsh" +#include "rs_graphics.rsh" + +rs_element elementTest; +rs_type typeTest; +rs_allocation allocationTest; +rs_sampler samplerTest; +rs_script scriptTest; +rs_mesh meshTest; +rs_program_fragment program_fragmentTest; +rs_program_vertex program_vertexTest; +rs_program_raster program_rasterTest; +rs_program_store program_storeTest; +rs_font fontTest; + +rs_matrix4x4 matrix4x4Test; +rs_matrix3x3 matrix3x3Test; +rs_matrix2x2 matrix2x2Test; + +struct my_struct { + int i; + rs_font fontTestStruct; +}; + +static bool basic_test(uint32_t index) { + bool failed = false; + + rs_matrix4x4 matrix4x4TestLocal; + rs_matrix3x3 matrix3x3TestLocal; + rs_matrix2x2 matrix2x2TestLocal; + + // This test focuses primarily on compilation-time, not run-time. + rs_element elementTestLocal; + rs_type typeTestLocal; + rs_allocation allocationTestLocal; + rs_sampler samplerTestLocal; + rs_script scriptTestLocal; + rs_mesh meshTestLocal; + rs_program_fragment program_fragmentTestLocal; + rs_program_vertex program_vertexTestLocal; + rs_program_raster program_rasterTestLocal; + rs_program_store program_storeTestLocal; + rs_font fontTestLocal; + + rs_font fontTestLocalArray[4]; + + rs_font fontTestLocalPreInit = fontTest; + + struct my_struct structTest; + + rsSetObject(&fontTestLocal, fontTest); + //allocationTestLocal = allocationTest; + + rsSetObject(&fontTest, fontTestLocal); + //allocationTest = allocationTestLocal; + + /*for (int i = 0; i < 4; i++) { + rsSetObject(&fontTestLocalArray[i], fontTestLocal); + }*/ + + /*rsSetObject(&fontTest, fontTestLocalArray[3]);*/ + + return failed; +} + +void test_rstypes(uint32_t index, int test_num) { + bool failed = false; + failed |= basic_test(index); + + if (failed) { + rsSendToClientBlocking(RS_MSG_TEST_FAILED); + rsDebug("rstypes_test FAILED", -1); + } + else { + rsSendToClientBlocking(RS_MSG_TEST_PASSED); + rsDebug("rstypes_test PASSED", 0); + } +} + diff --git a/libs/rs/java/tests/src/com/android/rs/test/shared.rsh b/libs/rs/java/tests/src/com/android/rs/test/shared.rsh new file mode 100644 index 0000000..21be9af --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/shared.rsh @@ -0,0 +1,38 @@ +#pragma version(1) + +#pragma rs java_package_name(com.android.rs.test) + +typedef struct TestResult_s { + rs_allocation name; + bool pass; + float score; + int64_t time; +} TestResult; +//TestResult *g_results; + +static int64_t g_time; + +static void start(void) { + g_time = rsUptimeMillis(); +} + +static float end(uint32_t idx) { + int64_t t = rsUptimeMillis() - g_time; + //g_results[idx].time = t; + //rsDebug("test time", (int)t); + return ((float)t) / 1000.f; +} + +#define _RS_ASSERT(b) \ +do { \ + if (!(b)) { \ + failed = true; \ + rsDebug(#b " FAILED", 0); \ + } \ +\ +} while (0) + +/* These constants must match those in UnitTest.java */ +static const int RS_MSG_TEST_PASSED = 100; +static const int RS_MSG_TEST_FAILED = 101; + diff --git a/libs/rs/java/tests/src/com/android/rs/test/test_root.rs b/libs/rs/java/tests/src/com/android/rs/test/test_root.rs new file mode 100644 index 0000000..6dc83ba --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/test_root.rs @@ -0,0 +1,23 @@ +// Fountain test script +#pragma version(1) + +#pragma rs java_package_name(com.android.rs.test) + +#pragma stateFragment(parent) + +#include "rs_graphics.rsh" + + +typedef struct TestResult { + rs_allocation name; + bool pass; + float score; +} TestResult_t; +TestResult_t *results; + +int root() { + + return 0; +} + + diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index 5ae8d01..7e23cec 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -1,11 +1,14 @@ +ContextFinish { + handcodeApi + } ContextBindRootScript { param RsScript sampler } -ContextBindProgramFragmentStore { - param RsProgramFragmentStore pgm +ContextBindProgramStore { + param RsProgramStore pgm } ContextBindProgramFragment { @@ -20,6 +23,10 @@ ContextBindProgramRaster { param RsProgramRaster pgm } +ContextBindFont { + param RsFont pgm + } + ContextPause { } @@ -36,15 +43,13 @@ ContextDump { param int32_t bits } -ContextGetError { - param RsError *err - ret const char * - } - ContextSetPriority { param int32_t priority } +ContextDestroyWorker { +} + AssignName { param void *obj param const char *name @@ -52,7 +57,7 @@ AssignName { } ObjDestroy { - param void *obj + param RsAsyncVoidPtr objPtr } ElementCreate { @@ -68,160 +73,86 @@ ElementCreate2 { param const RsElement * elements param const char ** names param const size_t * nameLengths + param const uint32_t * arraySize ret RsElement } -TypeBegin { - param RsElement type - } - -TypeAdd { - param RsDimension dim - param size_t value - } - -TypeCreate { - ret RsType - } - -AllocationCreateTyped { - param RsType type - ret RsAllocation - } - -AllocationCreateSized { - param RsElement e - param size_t count - ret RsAllocation - } - -AllocationCreateBitmapRef { - param RsType type - param void * bmpPtr - param void * callbackData - param RsBitmapCallback_t callback - ret RsAllocation - } - -AllocationCreateFromBitmap { - param uint32_t width - param uint32_t height - param RsElement dstFmt - param RsElement srcFmt - param bool genMips - param const void * data - ret RsAllocation - } - -AllocationCreateFromBitmapBoxed { - param uint32_t width - param uint32_t height - param RsElement dstFmt - param RsElement srcFmt - param bool genMips - param const void * data - ret RsAllocation - } - - -AllocationUploadToTexture { - param RsAllocation alloc - param bool genMipMaps - param uint32_t baseMipLevel - } - -AllocationUploadToBufferObject { +AllocationCopyToBitmap { param RsAllocation alloc + param void * data + param size_t dataLen } -AllocationData { +Allocation1DData { param RsAllocation va - param const void * data + param uint32_t xoff + param uint32_t lod + param uint32_t count + param const void *data param uint32_t bytes handcodeApi togglePlay } -Allocation1DSubData { +Allocation1DElementData { param RsAllocation va - param uint32_t xoff - param uint32_t count + param uint32_t x + param uint32_t lod param const void *data + param uint32_t comp_offset param uint32_t bytes handcodeApi togglePlay } -Allocation2DSubData { +Allocation2DData { param RsAllocation va param uint32_t xoff param uint32_t yoff + param uint32_t lod + param RsAllocationCubemapFace face param uint32_t w param uint32_t h param const void *data param uint32_t bytes } -AllocationRead { +Allocation2DElementData { param RsAllocation va - param void * data - } - -Adapter1DCreate { - ret RsAdapter1D - } - -Adapter1DBindAllocation { - param RsAdapter1D adapt - param RsAllocation alloc - } - -Adapter1DSetConstraint { - param RsAdapter1D adapter - param RsDimension dim - param uint32_t value - } - -Adapter1DData { - param RsAdapter1D adapter - param const void * data - } - -Adapter1DSubData { - param RsAdapter1D adapter - param uint32_t xoff - param uint32_t count + param uint32_t x + param uint32_t y + param uint32_t lod + param RsAllocationCubemapFace face param const void *data + param uint32_t element_offset + param uint32_t bytes } -Adapter2DCreate { - ret RsAdapter2D - } +AllocationGenerateMipmaps { + param RsAllocation va +} -Adapter2DBindAllocation { - param RsAdapter2D adapt - param RsAllocation alloc +AllocationRead { + param RsAllocation va + param void * data } -Adapter2DSetConstraint { - param RsAdapter2D adapter - param RsDimension dim - param uint32_t value - } +AllocationSyncAll { + param RsAllocation va + param RsAllocationUsageType src +} -Adapter2DData { - param RsAdapter2D adapter - param const void *data + +AllocationResize1D { + param RsAllocation va + param uint32_t dimX } -Adapter2DSubData { - param RsAdapter2D adapter - param uint32_t xoff - param uint32_t yoff - param uint32_t w - param uint32_t h - param const void *data +AllocationResize2D { + param RsAllocation va + param uint32_t dimX + param uint32_t dimY } SamplerBegin { @@ -232,6 +163,11 @@ SamplerSet { param RsSamplerValue value } +SamplerSet2 { + param RsSamplerParam p + param float value + } + SamplerCreate { ret RsSampler } @@ -248,13 +184,6 @@ ScriptBindAllocation { ScriptCBegin { } -ScriptSetClearColor { - param RsScript s - param float r - param float g - param float b - param float a - } ScriptSetTimeZone { param RsScript s @@ -262,98 +191,108 @@ ScriptSetTimeZone { param uint32_t length } -ScriptSetClearDepth { + +ScriptInvoke { param RsScript s - param float depth + param uint32_t slot } -ScriptSetClearStencil { +ScriptInvokeV { param RsScript s - param uint32_t stencil + param uint32_t slot + param const void * data + param uint32_t dataLen + handcodeApi + togglePlay } -ScriptSetType { - param RsType type +ScriptSetVarI { + param RsScript s param uint32_t slot - param bool isWritable - param const char * name + param int value } -ScriptSetInvoke { - param const char * name +ScriptSetVarObj { + param RsScript s param uint32_t slot + param RsObjectBase value } -ScriptInvoke { +ScriptSetVarJ { param RsScript s param uint32_t slot + param int64_t value } -ScriptSetRoot { - param bool isRoot +ScriptSetVarF { + param RsScript s + param uint32_t slot + param float value } +ScriptSetVarD { + param RsScript s + param uint32_t slot + param double value + } - -ScriptCSetScript { - param void * codePtr +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 ret RsScript } -ScriptCSetDefineF { - param const char* name - param float value - } - -ScriptCSetDefineI32 { - param const char* name - param int32_t value - } -ProgramFragmentStoreBegin { +ProgramStoreBegin { param RsElement in param RsElement out } -ProgramFragmentStoreColorMask { +ProgramStoreColorMask { param bool r param bool g param bool b param bool a } -ProgramFragmentStoreBlendFunc { +ProgramStoreBlendFunc { param RsBlendSrcFunc srcFunc param RsBlendDstFunc destFunc } -ProgramFragmentStoreDepthMask { +ProgramStoreDepthMask { param bool enable } -ProgramFragmentStoreDither { +ProgramStoreDither { param bool enable } -ProgramFragmentStoreDepthFunc { +ProgramStoreDepthFunc { param RsDepthFunc func } -ProgramFragmentStoreCreate { - ret RsProgramFragmentStore +ProgramStoreCreate { + ret RsProgramStore } ProgramRasterCreate { - param RsElement in - param RsElement out param bool pointSmooth param bool lineSmooth param bool pointSprite @@ -365,12 +304,11 @@ ProgramRasterSetLineWidth { param float lw } -ProgramRasterSetPointSize{ +ProgramRasterSetCullMode { param RsProgramRaster pr - param float ps + param RsCullMode mode } - ProgramBindConstants { param RsProgram vp param uint32_t slot @@ -391,12 +329,6 @@ ProgramBindSampler { } ProgramFragmentCreate { - param const uint32_t * params - param uint32_t paramLength - ret RsProgramFragment - } - -ProgramFragmentCreate2 { param const char * shaderText param uint32_t shaderLength param const uint32_t * params @@ -405,11 +337,6 @@ ProgramFragmentCreate2 { } ProgramVertexCreate { - param bool texMat - ret RsProgramVertex - } - -ProgramVertexCreate2 { param const char * shaderText param uint32_t shaderLength param const uint32_t * params @@ -417,66 +344,52 @@ ProgramVertexCreate2 { ret RsProgramVertex } -LightBegin { - } - -LightSetLocal { - param bool isLocal - } - -LightSetMonochromatic { - param bool isMono - } - -LightCreate { - ret RsLight light - } - - -LightSetPosition { - param RsLight light - param float x - param float y - param float z - } - -LightSetColor { - param RsLight light - param float r - param float g - param float b +FontCreateFromFile { + param const char *name + param float fontSize + param uint32_t dpi + ret RsFont } -FileOpen { - ret RsFile +FontCreateFromMemory { param const char *name - param size_t len + param float fontSize + param uint32_t dpi + param const void *data + param uint32_t dataLen + ret RsFont } - -SimpleMeshCreate { - ret RsSimpleMesh - param RsAllocation prim - param RsAllocation index - param RsAllocation *vtx +MeshCreate { + ret RsMesh param uint32_t vtxCount - param uint32_t primType + param uint32_t idxCount } - -SimpleMeshBindIndex { - param RsSimpleMesh mesh +MeshBindIndex { + param RsMesh mesh param RsAllocation idx + param uint32_t primType + param uint32_t slot } -SimpleMeshBindPrimitive { - param RsSimpleMesh mesh - param RsAllocation prim - } - -SimpleMeshBindVertex { - param RsSimpleMesh mesh +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/rsAdapter.cpp b/libs/rs/rsAdapter.cpp index 0d31fac..8d363fd 100644 --- a/libs/rs/rsAdapter.cpp +++ b/libs/rs/rsAdapter.cpp @@ -15,37 +15,32 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif using namespace android; using namespace android::renderscript; - -Adapter1D::Adapter1D(Context *rsc) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +Adapter1D::Adapter1D(Context *rsc) : ObjectBase(rsc) { reset(); } -Adapter1D::Adapter1D(Context *rsc, Allocation *a) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +Adapter1D::Adapter1D(Context *rsc, Allocation *a) : ObjectBase(rsc) { reset(); setAllocation(a); } -void Adapter1D::reset() -{ +void Adapter1D::reset() { mY = 0; mZ = 0; mLOD = 0; mFace = 0; } -void * Adapter1D::getElement(uint32_t x) -{ +void * Adapter1D::getElement(uint32_t x) { rsAssert(mAllocation.get()); rsAssert(mAllocation->getPtr()); rsAssert(mAllocation->getType()); @@ -54,8 +49,7 @@ void * Adapter1D::getElement(uint32_t x) return ptr; } -void Adapter1D::subData(uint32_t xoff, uint32_t count, const void *data) -{ +void Adapter1D::subData(uint32_t xoff, uint32_t count, const void *data) { if (mAllocation.get() && mAllocation.get()->getType()) { void *ptr = getElement(xoff); count *= mAllocation.get()->getType()->getElementSizeBytes(); @@ -63,34 +57,37 @@ void Adapter1D::subData(uint32_t xoff, uint32_t count, const void *data) } } -void Adapter1D::data(const void *data) -{ +void Adapter1D::data(const void *data) { memcpy(getElement(0), data, mAllocation.get()->getType()->getSizeBytes()); } +void Adapter1D::serialize(OStream *stream) const { +} + +Adapter1D *Adapter1D::createFromStream(Context *rsc, IStream *stream) { + return NULL; +} + namespace android { namespace renderscript { -RsAdapter1D rsi_Adapter1DCreate(Context *rsc) -{ +RsAdapter1D rsi_Adapter1DCreate(Context *rsc) { Adapter1D *a = new Adapter1D(rsc); a->incUserRef(); return a; } -void rsi_Adapter1DBindAllocation(Context *rsc, RsAdapter1D va, RsAllocation valloc) -{ +void rsi_Adapter1DBindAllocation(Context *rsc, RsAdapter1D va, RsAllocation valloc) { Adapter1D * a = static_cast<Adapter1D *>(va); Allocation * alloc = static_cast<Allocation *>(valloc); a->setAllocation(alloc); } -void rsi_Adapter1DSetConstraint(Context *rsc, RsAdapter1D va, RsDimension dim, uint32_t value) -{ +void rsi_Adapter1DSetConstraint(Context *rsc, RsAdapter1D va, RsDimension dim, uint32_t value) { Adapter1D * a = static_cast<Adapter1D *>(va); - switch(dim) { + switch (dim) { case RS_DIMENSION_X: rsAssert(!"Cannot contrain X in an 1D adapter"); return; @@ -112,14 +109,12 @@ void rsi_Adapter1DSetConstraint(Context *rsc, RsAdapter1D va, RsDimension dim, u } } -void rsi_Adapter1DSubData(Context *rsc, RsAdapter1D va, uint32_t xoff, uint32_t count, const void *data) -{ +void rsi_Adapter1DSubData(Context *rsc, RsAdapter1D va, uint32_t xoff, uint32_t count, const void *data) { Adapter1D * a = static_cast<Adapter1D *>(va); a->subData(xoff, count, data); } -void rsi_Adapter1DData(Context *rsc, RsAdapter1D va, const void *data) -{ +void rsi_Adapter1DData(Context *rsc, RsAdapter1D va, const void *data) { Adapter1D * a = static_cast<Adapter1D *>(va); a->data(data); } @@ -129,47 +124,48 @@ void rsi_Adapter1DData(Context *rsc, RsAdapter1D va, const void *data) ////////////////////////// -Adapter2D::Adapter2D(Context *rsc) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +Adapter2D::Adapter2D(Context *rsc) : ObjectBase(rsc) { reset(); } -Adapter2D::Adapter2D(Context *rsc, Allocation *a) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +Adapter2D::Adapter2D(Context *rsc, Allocation *a) : ObjectBase(rsc) { reset(); setAllocation(a); } -void Adapter2D::reset() -{ +void Adapter2D::reset() { mZ = 0; mLOD = 0; mFace = 0; } -void * Adapter2D::getElement(uint32_t x, uint32_t y) const -{ +void * Adapter2D::getElement(uint32_t x, uint32_t y) const { rsAssert(mAllocation.get()); rsAssert(mAllocation->getPtr()); rsAssert(mAllocation->getType()); + if (mFace != 0 && !mAllocation->getType()->getDimFaces()) { + LOGE("Adapter wants cubemap face, but allocation has none"); + return NULL; + } + uint8_t * ptr = static_cast<uint8_t *>(mAllocation->getPtr()); ptr += mAllocation->getType()->getLODOffset(mLOD, x, y); + + if (mFace != 0) { + uint32_t totalSizeBytes = mAllocation->getType()->getSizeBytes(); + uint32_t faceOffset = totalSizeBytes / 6; + ptr += faceOffset * mFace; + } return ptr; } -void Adapter2D::subData(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data) -{ +void Adapter2D::subData(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data) { rsAssert(mAllocation.get()); rsAssert(mAllocation->getPtr()); rsAssert(mAllocation->getType()); uint32_t eSize = mAllocation.get()->getType()->getElementSizeBytes(); uint32_t lineSize = eSize * w; - uint32_t destW = getDimX(); const uint8_t *src = static_cast<const uint8_t *>(data); for (uint32_t line=yoff; line < (yoff+h); line++) { @@ -178,36 +174,38 @@ void Adapter2D::subData(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, co } } -void Adapter2D::data(const void *data) -{ +void Adapter2D::data(const void *data) { memcpy(getElement(0,0), data, mAllocation.get()->getType()->getSizeBytes()); } +void Adapter2D::serialize(OStream *stream) const { +} + +Adapter2D *Adapter2D::createFromStream(Context *rsc, IStream *stream) { + return NULL; +} namespace android { namespace renderscript { -RsAdapter2D rsi_Adapter2DCreate(Context *rsc) -{ +RsAdapter2D rsi_Adapter2DCreate(Context *rsc) { Adapter2D *a = new Adapter2D(rsc); a->incUserRef(); return a; } -void rsi_Adapter2DBindAllocation(Context *rsc, RsAdapter2D va, RsAllocation valloc) -{ +void rsi_Adapter2DBindAllocation(Context *rsc, RsAdapter2D va, RsAllocation valloc) { Adapter2D * a = static_cast<Adapter2D *>(va); Allocation * alloc = static_cast<Allocation *>(valloc); a->setAllocation(alloc); } -void rsi_Adapter2DSetConstraint(Context *rsc, RsAdapter2D va, RsDimension dim, uint32_t value) -{ +void rsi_Adapter2DSetConstraint(Context *rsc, RsAdapter2D va, RsDimension dim, uint32_t value) { Adapter2D * a = static_cast<Adapter2D *>(va); - switch(dim) { + switch (dim) { case RS_DIMENSION_X: rsAssert(!"Cannot contrain X in an 2D adapter"); return; @@ -229,14 +227,12 @@ void rsi_Adapter2DSetConstraint(Context *rsc, RsAdapter2D va, RsDimension dim, u } } -void rsi_Adapter2DData(Context *rsc, RsAdapter2D va, const void *data) -{ +void rsi_Adapter2DData(Context *rsc, RsAdapter2D va, const void *data) { Adapter2D * a = static_cast<Adapter2D *>(va); a->data(data); } -void rsi_Adapter2DSubData(Context *rsc, RsAdapter2D va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data) -{ +void rsi_Adapter2DSubData(Context *rsc, RsAdapter2D va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data) { Adapter2D * a = static_cast<Adapter2D *>(va); a->subData(xoff, yoff, w, h, data); } diff --git a/libs/rs/rsAdapter.h b/libs/rs/rsAdapter.h index cb2872e..d150789 100644 --- a/libs/rs/rsAdapter.h +++ b/libs/rs/rsAdapter.h @@ -24,8 +24,7 @@ namespace android { namespace renderscript { -class Adapter1D : public ObjectBase -{ +class Adapter1D : public ObjectBase { public: // By policy this allocation will hold a pointer to the type @@ -50,6 +49,10 @@ public: void subData(uint32_t xoff, uint32_t count, const void *data); void data(const void *data); + virtual void serialize(OStream *stream) const; + virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ADAPTER_1D; } + static Adapter1D *createFromStream(Context *rsc, IStream *stream); + protected: ObjectBaseRef<Allocation> mAllocation; uint32_t mY; @@ -58,8 +61,7 @@ protected: uint32_t mFace; }; -class Adapter2D : public ObjectBase -{ +class Adapter2D : public ObjectBase { public: // By policy this allocation will hold a pointer to the type @@ -82,6 +84,10 @@ public: void data(const void *data); void subData(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data); + virtual void serialize(OStream *stream) const; + virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ADAPTER_2D; } + static Adapter2D *createFromStream(Context *rsc, IStream *stream); + protected: ObjectBaseRef<Allocation> mAllocation; uint32_t mZ; @@ -89,7 +95,6 @@ protected: uint32_t mFace; }; - } } #endif diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp index 4e8278d..41c9fe2 100644 --- a/libs/rs/rsAllocation.cpp +++ b/libs/rs/rsAllocation.cpp @@ -13,41 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" #include <GLES/gl.h> #include <GLES2/gl2.h> #include <GLES/glext.h> +#else +#include "rsContextHostStub.h" + +#include <OpenGL/gl.h> +#include <OpenGl/glext.h> +#endif + +#include "utils/StopWatch.h" + +static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va); using namespace android; using namespace android::renderscript; -Allocation::Allocation(Context *rsc, const Type *type) : ObjectBase(rsc) -{ +Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages, + RsAllocationMipmapControl mc) + : ObjectBase(rsc) { init(rsc, type); - mPtr = malloc(mType->getSizeBytes()); + mUsageFlags = usages; + mMipmapControl = mc; + + allocScriptMemory(); + if (mType->getElement()->getHasReferences()) { + memset(mPtr, 0, mType->getSizeBytes()); + } if (!mPtr) { LOGE("Allocation::Allocation, alloc failure"); } } -Allocation::Allocation(Context *rsc, const Type *type, void *bmp, - void *callbackData, RsBitmapCallback_t callback) -: ObjectBase(rsc) -{ - init(rsc, type); - mPtr = bmp; - mUserBitmapCallback = callback; - mUserBitmapCallbackData = callbackData; -} - -void Allocation::init(Context *rsc, const Type *type) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +void Allocation::init(Context *rsc, const Type *type) { mPtr = NULL; mCpuWrite = false; @@ -57,10 +61,10 @@ void Allocation::init(Context *rsc, const Type *type) mReadWriteRatio = 0; mUpdateSize = 0; + mUsageFlags = 0; + mMipmapControl = RS_ALLOCATION_MIPMAP_NONE; - mIsTexture = false; mTextureID = 0; - mIsVertexBuffer = false; mBufferID = 0; mUploadDefered = false; @@ -73,14 +77,12 @@ void Allocation::init(Context *rsc, const Type *type) mPtr = NULL; } -Allocation::~Allocation() -{ +Allocation::~Allocation() { if (mUserBitmapCallback != NULL) { mUserBitmapCallback(mUserBitmapCallbackData); - } else { - free(mPtr); + mPtr = NULL; } - mPtr = NULL; + freeScriptMemory(); if (mBufferID) { // Causes a SW crash.... @@ -94,46 +96,70 @@ Allocation::~Allocation() } } -void Allocation::setCpuWritable(bool) -{ +void Allocation::setCpuWritable(bool) { } -void Allocation::setGpuWritable(bool) -{ +void Allocation::setGpuWritable(bool) { } -void Allocation::setCpuReadable(bool) -{ +void Allocation::setCpuReadable(bool) { } -void Allocation::setGpuReadable(bool) -{ +void Allocation::setGpuReadable(bool) { } -bool Allocation::fixAllocation() -{ +bool Allocation::fixAllocation() { return false; } -void Allocation::deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset) -{ - rsAssert(lodOffset < mType->getLODCount()); - mIsTexture = true; - mTextureLOD = lodOffset; +void Allocation::deferedUploadToTexture(const Context *rsc) { + mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE; mUploadDefered = true; - mTextureGenMipmap = !mType->getDimLOD() && genMipmap; } -void Allocation::uploadToTexture(const Context *rsc) -{ - //rsAssert(!mTextureId); +uint32_t Allocation::getGLTarget() const { + if (getIsTexture()) { + if (mType->getDimFaces()) { + return GL_TEXTURE_CUBE_MAP; + } else { + return GL_TEXTURE_2D; + } + } + if (getIsBufferObject()) { + return GL_ARRAY_BUFFER; + } + return 0; +} + +void Allocation::allocScriptMemory() { + rsAssert(!mPtr); + mPtr = malloc(mType->getSizeBytes()); +} - mIsTexture = true; - if (!rsc->checkDriver()) { - mUploadDefered = true; - return; +void Allocation::freeScriptMemory() { + if (mPtr) { + free(mPtr); + mPtr = NULL; + } +} + + +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) { + + mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE; GLenum type = mType->getElement()->getComponent().getGLType(); GLenum format = mType->getElement()->getComponent().getGLFormat(); @@ -141,6 +167,12 @@ void Allocation::uploadToTexture(const Context *rsc) return; } + if (!mPtr) { + return; + } + + bool isFirstUpload = false; + if (!mTextureID) { glGenTextures(1, &mTextureID); @@ -153,41 +185,95 @@ void Allocation::uploadToTexture(const Context *rsc) mUploadDefered = true; return; } + isFirstUpload = true; } - glBindTexture(GL_TEXTURE_2D, mTextureID); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - Adapter2D adapt(getContext(), this); - for(uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) { - adapt.setLOD(lod+mTextureLOD); + upload2DTexture(isFirstUpload); - uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0)); - glTexImage2D(GL_TEXTURE_2D, lod, format, - adapt.getDimX(), adapt.getDimY(), - 0, format, type, ptr); + if (!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { + freeScriptMemory(); } - if (mTextureGenMipmap) { - glGenerateMipmap(GL_TEXTURE_2D); + + rsc->checkError("Allocation::uploadToTexture"); +} + +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 +}; + +void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff, + uint32_t lod, RsAllocationCubemapFace face, + uint32_t w, uint32_t h) { + 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); +} + +void Allocation::upload2DTexture(bool isFirstUpload) { + 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) { +#ifndef ANDROID_RS_BUILD_FOR_HOST + glGenerateMipmap(target); +#endif //ANDROID_RS_BUILD_FOR_HOST + } } -void Allocation::deferedUploadToBufferObject(const Context *rsc) -{ - mIsVertexBuffer = true; +void Allocation::deferedUploadToBufferObject(const Context *rsc) { + mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; mUploadDefered = true; } -void Allocation::uploadToBufferObject(const Context *rsc) -{ +void Allocation::uploadToBufferObject(const Context *rsc) { rsAssert(!mType->getDimY()); rsAssert(!mType->getDimZ()); - mIsVertexBuffer = true; - if (!rsc->checkDriver()) { - mUploadDefered = true; - return; - } + mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; if (!mBufferID) { glGenBuffers(1, &mBufferID); @@ -197,45 +283,25 @@ void Allocation::uploadToBufferObject(const Context *rsc) mUploadDefered = true; return; } - - glBindBuffer(GL_ARRAY_BUFFER, mBufferID); - glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + GLenum target = (GLenum)getGLTarget(); + glBindBuffer(target, mBufferID); + glBufferData(target, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW); + glBindBuffer(target, 0); + rsc->checkError("Allocation::uploadToBufferObject"); } -void Allocation::uploadCheck(const Context *rsc) -{ +void Allocation::uploadCheck(Context *rsc) { if (mUploadDefered) { - mUploadDefered = false; - if (mIsVertexBuffer) { - uploadToBufferObject(rsc); - } - if (mIsTexture) { - uploadToTexture(rsc); - } + syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT); } } - -void Allocation::data(const void *data, uint32_t sizeBytes) -{ - uint32_t size = mType->getSizeBytes(); - if (size != sizeBytes) { - LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes); - return; - } - memcpy(mPtr, data, size); - sendDirty(); - mUploadDefered = true; -} - -void Allocation::read(void *data) -{ +void Allocation::read(void *data) { memcpy(data, mPtr, mType->getSizeBytes()); } -void Allocation::subData(uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) -{ +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; @@ -246,49 +312,143 @@ void Allocation::subData(uint32_t xoff, uint32_t count, const void *data, uint32 mType->dumpLOGV("type info"); return; } + + if (mType->getElement()->getHasReferences()) { + incRefs(data, count); + decRefs(ptr, count); + } + memcpy(ptr, data, size); sendDirty(); mUploadDefered = true; } -void Allocation::subData(uint32_t xoff, uint32_t yoff, - uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) -{ +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 uint8_t *src = static_cast<const uint8_t *>(data); - uint8_t *dst = static_cast<uint8_t *>(mPtr); - dst += eSize * (xoff + yoff * destW); + //LOGE("data2d %p, %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes); - if ((lineSize * eSize * h) != sizeBytes) { + if ((lineSize * h) != sizeBytes) { + LOGE("Allocation size mismatch, expected %i, got %i", (lineSize * h), sizeBytes); rsAssert(!"Allocation::subData called with mismatched size"); return; } - for (uint32_t line=yoff; line < (yoff+h); line++) { - uint8_t * ptr = static_cast<uint8_t *>(mPtr); - memcpy(dst, src, lineSize); - src += lineSize; - dst += destW * eSize; + 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); + } +} + +void Allocation::data(Context *rsc, 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 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; + + if (cIdx >= mType->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()) { + 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); + + if (sizeBytes != e->getSizeBytes()) { + LOGE("Error Allocation::subElementData data size %i does not match field size %i.", 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; } -void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff, - uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) -{ +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()); + + if (x >= mType->getDimX()) { + 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()) { + 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()) { + 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); + + if (sizeBytes != e->getSizeBytes()) { + LOGE("Error Allocation::subElementData data size %i does not match field size %i.", 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; } -void Allocation::addProgramToDirty(const Program *p) -{ - mToDirtyList.add(p); +void Allocation::addProgramToDirty(const Program *p) { + mToDirtyList.push(p); } -void Allocation::removeProgramToDirty(const Program *p) -{ +void Allocation::removeProgramToDirty(const Program *p) { for (size_t ct=0; ct < mToDirtyList.size(); ct++) { if (mToDirtyList[ct] == p) { mToDirtyList.removeAt(ct); @@ -298,8 +458,7 @@ void Allocation::removeProgramToDirty(const Program *p) rsAssert(0); } -void Allocation::dumpLOGV(const char *prefix) const -{ +void Allocation::dumpLOGV(const char *prefix) const { ObjectBase::dumpLOGV(prefix); String8 s(prefix); @@ -311,57 +470,143 @@ void Allocation::dumpLOGV(const char *prefix) const LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i", prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead); - LOGV("%s allocation mIsTexture=%i mTextureID=%i, mIsVertexBuffer=%i, mBufferID=%i", - prefix, mIsTexture, mTextureID, mIsVertexBuffer, mBufferID); + LOGV("%s allocation mUsageFlags=0x04%x, mMipmapControl=0x%04x, mTextureID=%i, mBufferID=%i", + prefix, mUsageFlags, mMipmapControl, mTextureID, mBufferID); +} + +void Allocation::serialize(OStream *stream) const { + // Need to identify ourselves + stream->addU32((uint32_t)getClassId()); + String8 name(getName()); + stream->addString(&name); + + // First thing we need to serialize is the type object since it will be needed + // to initialize the class + mType->serialize(stream); + + uint32_t dataSize = mType->getSizeBytes(); + // Write how much data we are storing + stream->addU32(dataSize); + // Now write the data + stream->addByteArray(mPtr, dataSize); +} + +Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) { + // First make sure we are reading the correct object + RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); + if (classID != RS_A3D_CLASS_ID_ALLOCATION) { + LOGE("allocation loading skipped due to invalid class id\n"); + return NULL; + } + + String8 name; + stream->loadString(&name); + + Type *type = Type::createFromStream(rsc, stream); + if (!type) { + return NULL; + } + type->compute(); + + // Number of bytes we wrote out for this allocation + uint32_t dataSize = stream->loadU32(); + if (dataSize != type->getSizeBytes()) { + LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n"); + ObjectBase::checkDelete(type); + return NULL; + } + + Allocation *alloc = new Allocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT); + alloc->setName(name.string(), name.size()); + + uint32_t count = dataSize / type->getElementSizeBytes(); + + // Read in all of our allocation data + alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize); + stream->reset(stream->getPos() + dataSize); + + return alloc; } -void Allocation::sendDirty() const -{ +void Allocation::sendDirty() const { for (size_t ct=0; ct < mToDirtyList.size(); ct++) { mToDirtyList[ct]->forceDirty(); } } -///////////////// -// +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(); + uint32_t stride = e->getSizeBytes(); + p += stride * startOff; + while (ct > 0) { + e->incRefs(p); + ct --; + p += stride; + } +} -namespace android { -namespace renderscript { +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(); + uint32_t stride = e->getSizeBytes(); -RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype) -{ - const Type * type = static_cast<const Type *>(vtype); + p += stride * startOff; + while (ct > 0) { + e->decRefs(p); + ct --; + p += stride; + } +} - Allocation * alloc = new Allocation(rsc, type); - alloc->incUserRef(); - return alloc; +void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) { } -RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count) -{ - Type * type = new Type(rsc); - type->setDimX(count); - type->setElement(static_cast<Element *>(e)); - type->compute(); - return rsi_AllocationCreateTyped(rsc, type); +void Allocation::resize1D(Context *rsc, uint32_t dimX) { + Type *t = mType->cloneAndResize1D(rsc, dimX); + + uint32_t oldDimX = mType->getDimX(); + if (dimX == oldDimX) { + return; + } + + if (dimX < oldDimX) { + decRefs(mPtr, 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); } -void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel) -{ +void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) { + LOGE("not implemented"); +} + +///////////////// +// + + +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, genmip, baseMipLevel); + alloc->deferedUploadToTexture(rsc); } -void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) -{ +void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) { Allocation *alloc = static_cast<Allocation *>(va); alloc->deferedUploadToBufferObject(rsc); } -static void mip565(const Adapter2D &out, const Adapter2D &in) -{ +static void mip565(const Adapter2D &out, const Adapter2D &in) { uint32_t w = out.getDimX(); uint32_t h = out.getDimY(); @@ -379,8 +624,7 @@ static void mip565(const Adapter2D &out, const Adapter2D &in) } } -static void mip8888(const Adapter2D &out, const Adapter2D &in) -{ +static void mip8888(const Adapter2D &out, const Adapter2D &in) { uint32_t w = out.getDimX(); uint32_t h = out.getDimY(); @@ -398,8 +642,7 @@ static void mip8888(const Adapter2D &out, const Adapter2D &in) } } -static void mip8(const Adapter2D &out, const Adapter2D &in) -{ +static void mip8(const Adapter2D &out, const Adapter2D &in) { uint32_t w = out.getDimX(); uint32_t h = out.getDimY(); @@ -417,9 +660,8 @@ static void mip8(const Adapter2D &out, const Adapter2D &in) } } -static void mip(const Adapter2D &out, const Adapter2D &in) -{ - switch(out.getBaseType()->getElement()->getSizeBits()) { +static void mip(const Adapter2D &out, const Adapter2D &in) { + switch (out.getBaseType()->getElement()->getSizeBits()) { case 32: mip8888(out, in); break; @@ -429,190 +671,171 @@ static void mip(const Adapter2D &out, const Adapter2D &in) case 8: mip8(out, in); break; - } - } -typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count); +#ifndef ANDROID_RS_BUILD_FOR_HOST -static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count) -{ - memcpy(dst, src, count * 2); -} -static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count) -{ - memcpy(dst, src, count); -} -static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count) -{ - memcpy(dst, src, count * 4); +void rsi_AllocationSyncAll(Context *rsc, RsAllocation va, RsAllocationUsageType src) { + Allocation *a = static_cast<Allocation *>(va); + a->syncAll(rsc, src); } +void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) { + Allocation *texAlloc = static_cast<Allocation *>(va); + rsaAllocationGenerateScriptMips(rsc, texAlloc); +} -static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count) -{ - uint16_t *d = static_cast<uint16_t *>(dst); - const uint8_t *s = static_cast<const uint8_t *>(src); +void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) { + Allocation *texAlloc = static_cast<Allocation *>(va); + const Type * t = texAlloc->getType(); - while(count--) { - *d = rs888to565(s[0], s[1], s[2]); - d++; - s+= 3; + size_t s = t->getDimX() * t->getDimY() * t->getElementSizeBytes(); + if (s != dataLen) { + rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size"); + return; } + + memcpy(data, texAlloc->getPtr(), s); } -static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count) -{ - uint16_t *d = static_cast<uint16_t *>(dst); - const uint8_t *s = static_cast<const uint8_t *>(src); +void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod, + uint32_t count, const void *data, uint32_t sizeBytes) { + Allocation *a = static_cast<Allocation *>(va); + a->data(rsc, xoff, lod, count, data, sizeBytes); +} - while(count--) { - *d = rs888to565(s[0], s[1], s[2]); - d++; - s+= 4; - } +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) { + 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) { + Allocation *a = static_cast<Allocation *>(va); + a->elementData(rsc, x, data, eoff, sizeBytes); } -static ElementConverter_t pickConverter(const Element *dst, const Element *src) -{ - GLenum srcGLType = src->getComponent().getGLType(); - GLenum srcGLFmt = src->getComponent().getGLFormat(); - GLenum dstGLType = dst->getComponent().getGLType(); - GLenum dstGLFmt = dst->getComponent().getGLFormat(); +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) { + Allocation *a = static_cast<Allocation *>(va); + a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes); +} - if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) { - switch(dst->getSizeBytes()) { - case 4: - return elementConverter_cpy_32; - case 2: - return elementConverter_cpy_16; - case 1: - return elementConverter_cpy_8; - } - } +void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) { + Allocation *a = static_cast<Allocation *>(va); + a->read(data); +} - if (srcGLType == GL_UNSIGNED_BYTE && - srcGLFmt == GL_RGB && - dstGLType == GL_UNSIGNED_SHORT_5_6_5 && - dstGLType == GL_RGB) { +void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX) { + Allocation *a = static_cast<Allocation *>(va); + a->resize1D(rsc, dimX); +} - return elementConverter_888_to_565; - } +void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY) { + Allocation *a = static_cast<Allocation *>(va); + a->resize2D(rsc, dimX, dimY); +} + +#endif //ANDROID_RS_BUILD_FOR_HOST - if (srcGLType == GL_UNSIGNED_BYTE && - srcGLFmt == GL_RGBA && - dstGLType == GL_UNSIGNED_SHORT_5_6_5 && - dstGLType == GL_RGB) { +} +} - return elementConverter_8888_to_565; +static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va) { + Context *rsc = static_cast<Context *>(con); + Allocation *texAlloc = static_cast<Allocation *>(va); + uint32_t numFaces = texAlloc->getType()->getDimFaces() ? 6 : 1; + for (uint32_t face = 0; face < numFaces; face ++) { + Adapter2D adapt(rsc, texAlloc); + Adapter2D adapt2(rsc, texAlloc); + adapt.setFace(face); + adapt2.setFace(face); + for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) { + adapt.setLOD(lod); + adapt2.setLOD(lod + 1); + mip(adapt2, adapt); + } } +} - LOGE("pickConverter, unsuported combo, src %p, dst %p", src, dst); - return 0; +const void * rsaAllocationGetType(RsContext con, RsAllocation va) { + Allocation *a = static_cast<Allocation *>(va); + a->getType()->incUserRef(); + + return a->getType(); } -RsAllocation rsi_AllocationCreateBitmapRef(Context *rsc, RsType vtype, - void *bmp, void *callbackData, RsBitmapCallback_t callback) -{ - const Type * type = static_cast<const Type *>(vtype); - Allocation * alloc = new Allocation(rsc, type, bmp, callbackData, callback); +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); alloc->incUserRef(); return alloc; } -RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data) -{ - const Element *src = static_cast<const Element *>(_src); - const Element *dst = static_cast<const Element *>(_dst); - // Check for pow2 on pre es 2.0 versions. - rsAssert(rsc->checkVersion2_0() || (!(w & (w-1)) && !(h & (h-1)))); +RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype, + RsAllocationMipmapControl mips, + const void *data, uint32_t usages) { + Context *rsc = static_cast<Context *>(con); + Type *t = static_cast<Type *>(vtype); - //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips); - rsi_TypeBegin(rsc, _dst); - rsi_TypeAdd(rsc, RS_DIMENSION_X, w); - rsi_TypeAdd(rsc, RS_DIMENSION_Y, h); - if (genMips) { - rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1); - } - RsType type = rsi_TypeCreate(rsc); - - RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type); + RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, vtype, mips, usages); Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc); if (texAlloc == NULL) { LOGE("Memory allocation failure"); return NULL; } - ElementConverter_t cvt = pickConverter(dst, src); - cvt(texAlloc->getPtr(), data, w * h); - - if (genMips) { - Adapter2D adapt(rsc, texAlloc); - Adapter2D adapt2(rsc, texAlloc); - for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) { - adapt.setLOD(lod); - adapt2.setLOD(lod + 1); - mip(adapt2, adapt); - } + memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes()); + if (mips == RS_ALLOCATION_MIPMAP_FULL) { + rsaAllocationGenerateScriptMips(rsc, texAlloc); } + texAlloc->deferedUploadToTexture(rsc); return texAlloc; } -RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data) -{ - const Element *srcE = static_cast<const Element *>(_src); - const Element *dstE = static_cast<const Element *>(_dst); - uint32_t w2 = rsHigherPow2(w); - uint32_t h2 = rsHigherPow2(h); +RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype, + RsAllocationMipmapControl mips, + const void *data, uint32_t usages) { + Context *rsc = static_cast<Context *>(con); + Type *t = static_cast<Type *>(vtype); - if ((w2 == w) && (h2 == h)) { - return rsi_AllocationCreateFromBitmap(rsc, w, h, _dst, _src, genMips, data); + // 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); + Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc); + if (texAlloc == NULL) { + LOGE("Memory allocation failure"); + return NULL; } - uint32_t bpp = srcE->getSizeBytes(); - size_t size = w2 * h2 * bpp; - uint8_t *tmp = static_cast<uint8_t *>(malloc(size)); - memset(tmp, 0, size); + uint32_t faceSize = t->getDimX(); + uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes(); + uint32_t copySize = faceSize * t->getElementSizeBytes(); - const uint8_t * src = static_cast<const uint8_t *>(data); - for (uint32_t y = 0; y < h; y++) { - uint8_t * ydst = &tmp[(y + ((h2 - h) >> 1)) * w2 * bpp]; - memcpy(&ydst[((w2 - w) >> 1) * bpp], src, w * bpp); - src += w * bpp; - } + uint8_t *sourcePtr = (uint8_t*)data; + for (uint32_t face = 0; face < 6; face ++) { + Adapter2D faceAdapter(rsc, texAlloc); + faceAdapter.setFace(face); - RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, _dst, _src, genMips, tmp); - free(tmp); - return ret; -} - -void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes) -{ - Allocation *a = static_cast<Allocation *>(va); - a->data(data, sizeBytes); -} - -void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) -{ - Allocation *a = static_cast<Allocation *>(va); - a->subData(xoff, count, data, sizeBytes); -} - -void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) -{ - Allocation *a = static_cast<Allocation *>(va); - a->subData(xoff, yoff, w, h, data, sizeBytes); -} + for (uint32_t dI = 0; dI < faceSize; dI ++) { + memcpy(faceAdapter.getElement(0, dI), sourcePtr + strideBytes * dI, copySize); + } -void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) -{ - Allocation *a = static_cast<Allocation *>(va); - a->read(data); -} + // Move the data pointer to the next cube face + sourcePtr += copySize; + } + if (mips == RS_ALLOCATION_MIPMAP_FULL) { + rsaAllocationGenerateScriptMips(rsc, texAlloc); + } -} + texAlloc->deferedUploadToTexture(rsc); + return texAlloc; } diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h index 516f8b7..4f5d5a8 100644 --- a/libs/rs/rsAllocation.h +++ b/libs/rs/rsAllocation.h @@ -25,15 +25,12 @@ namespace renderscript { class Program; -class Allocation : public ObjectBase -{ +class Allocation : public ObjectBase { // The graphics equilivent of malloc. The allocation contains a structure of elements. public: - // By policy this allocation will hold a pointer to the type - // but will not destroy it on destruction. - Allocation(Context *rsc, const Type *); - Allocation(Context *rsc, const Type *, void *bmp, void *callbackData, RsBitmapCallback_t callback); + Allocation(Context *rsc, const Type *, uint32_t usages, + RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE); virtual ~Allocation(); @@ -47,22 +44,34 @@ public: void * getPtr() const {return mPtr;} const Type * getType() const {return mType.get();} - void deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset); + 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); + void resize2D(Context *rsc, uint32_t dimX, uint32_t dimY); - void data(const void *data, uint32_t sizeBytes); - void subData(uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes); - void subData(uint32_t xoff, uint32_t yoff, + void data(Context *rsc, uint32_t xoff, uint32_t lod, uint32_t count, const void *data, uint32_t sizeBytes); + void 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); - void subData(uint32_t xoff, uint32_t yoff, uint32_t zoff, + void data(Context *rsc, 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 elementData(Context *rsc, uint32_t x, + const void *data, uint32_t elementOff, uint32_t sizeBytes); + void elementData(Context *rsc, uint32_t x, uint32_t y, + const void *data, uint32_t elementOff, uint32_t sizeBytes); + void read(void *data); void enableGLVertexBuffers() const; @@ -72,12 +81,32 @@ public: void removeProgramToDirty(const Program *); virtual void dumpLOGV(const char *prefix) const; + virtual void serialize(OStream *stream) const; + virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ALLOCATION; } + static Allocation *createFromStream(Context *rsc, IStream *stream); - virtual void uploadCheck(const Context *rsc); + virtual void uploadCheck(Context *rsc); + + bool getIsScript() const { + return (mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT) != 0; + } + bool getIsTexture() const { + return (mUsageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) != 0; + } + bool getIsBufferObject() const { + return (mUsageFlags & 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; -protected: void sendDirty() const; + bool getHasGraphicsMipmaps() const { + return mMipmapControl != RS_ALLOCATION_MIPMAP_NONE; + } + +protected: ObjectBaseRef<const Type> mType; void * mPtr; @@ -94,6 +123,9 @@ protected: 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 @@ -103,21 +135,23 @@ protected: // Is this a legal structure to be used as a texture source. // Initially this will require 1D or 2D and color data - bool mIsTexture; - bool mTextureGenMipmap; - uint32_t mTextureLOD; 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. - bool mIsVertexBuffer; 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(); }; diff --git a/libs/rs/rsAnimation.cpp b/libs/rs/rsAnimation.cpp new file mode 100644 index 0000000..6abda3c --- /dev/null +++ b/libs/rs/rsAnimation.cpp @@ -0,0 +1,145 @@ +/* + * 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. + */ + +#ifndef ANDROID_RS_BUILD_FOR_HOST +#include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif //ANDROID_RS_BUILD_FOR_HOST + +#include "rsAnimation.h" + + +using namespace android; +using namespace android::renderscript; + +void Animation::serialize(OStream *stream) const { +} + +Animation *Animation::createFromStream(Context *rsc, IStream *stream) { + return NULL; +} + +/* +Animation::Animation(Context *rsc) : ObjectBase(rsc) +{ + mAllocFile = __FILE__; + mAllocLine = __LINE__; + + mValuesInput = NULL; + mValuesOutput = NULL; + mValueCount = 0; + mInterpolation = RS_ANIMATION_INTERPOLATION_STEP; + mEdgePre = RS_ANIMATION_EDGE_UNDEFINED; + mEdgePost = RS_ANIMATION_EDGE_UNDEFINED; + mInputMin = 0; + mInputMax = 0; +} + +Animation * Animation::create(Context *rsc, + const float *inValues, const float *outValues, + uint32_t valueCount, RsAnimationInterpolation interp, + RsAnimationEdge pre, RsAnimationEdge post) +{ + if (valueCount < 2) { + rsc->setError(RS_ERROR_BAD_VALUE, "Animations require more than 2 values."); + return NULL; + } + Animation *a = new Animation(rsc); + if (!a) { + rsc->setError(RS_ERROR_OUT_OF_MEMORY); + return NULL; + } + + float *vin = (float *)malloc(valueCount * sizeof(float)); + float *vout = (float *)malloc(valueCount * sizeof(float)); + a->mValuesInput = vin; + a->mValuesOutput = vout; + if (a->mValuesInput == NULL || a->mValuesOutput == NULL) { + delete a; + rsc->setError(RS_ERROR_OUT_OF_MEMORY); + return NULL; + } + + a->mEdgePre = pre; + a->mEdgePost = post; + a->mInterpolation = interp; + a->mValueCount = valueCount; + + memcpy(vin, inValues, valueCount * sizeof(float)); + memcpy(vout, outValues, valueCount * sizeof(float)); + a->mInputMin = inValues[0]; + a->mInputMax = inValues[0]; + + bool needSort = false; + for (uint32_t ct=1; ct < valueCount; ct++) { + if (a->mInputMin > vin[ct]) { + needSort = true; + a->mInputMin = vin[ct]; + } + if (a->mInputMax < vin[ct]) { + a->mInputMax = vin[ct]; + } else { + needSort = true; + } + } + + while (1) { + bool changed = false; + for (uint32_t ct=1; ct < valueCount; ct++) { + if (vin[ct-1] > vin[ct]) { + float t = vin[ct-1]; + vin[ct-1] = vin[ct]; + vin[ct] = t; + t = vout[ct-1]; + vout[ct-1] = vout[ct]; + vout[ct] = t; + changed = true; + } + } + if (!changed) break; + } + + return a; +} +*/ + + +///////////////////////////////////////// +// + +namespace android { +namespace renderscript { + +RsAnimation rsi_AnimationCreate(Context *rsc, + const float *inValues, + const float *outValues, + uint32_t valueCount, + RsAnimationInterpolation interp, + RsAnimationEdge pre, + RsAnimationEdge post) { + //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize); + Animation *a = NULL;//Animation::create(rsc, inValues, outValues, valueCount, interp, pre, post); + if (a != NULL) { + a->incUserRef(); + } + return (RsAnimation)a; +} + + +} +} + diff --git a/libs/rs/rsAnimation.h b/libs/rs/rsAnimation.h new file mode 100644 index 0000000..bff8d6f --- /dev/null +++ b/libs/rs/rsAnimation.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef ANDROID_RS_ANIMATION_H +#define ANDROID_RS_ANIMATION_H + +#include "rsUtils.h" +#include "rsObjectBase.h" + +// --------------------------------------------------------------------------- +namespace android { +namespace renderscript { + + +class Animation : public ObjectBase { +public: + ~Animation(); + + static Animation * create(Context *rsc, + const float *inValues, const float *outValues, + uint32_t valueCount, RsAnimationInterpolation, + RsAnimationEdge pre, RsAnimationEdge post); + + float eval(float) const; + + virtual void serialize(OStream *stream) const; + virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ANIMATION; } + static Animation *createFromStream(Context *rsc, IStream *stream); + +protected: + Animation(Context *rsc); + + + + float evalInRange(float) const; + + + + const float *mValuesInput; + const float *mValuesOutput; + uint32_t mValueCount; + RsAnimationInterpolation mInterpolation; + RsAnimationEdge mEdgePre; + RsAnimationEdge mEdgePost; + + // derived + float mInputMin; + float mInputMax; +}; + +} +} +#endif //ANDROID_STRUCTURED_ELEMENT_H + diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp index 15a56f7..81ade5d 100644 --- a/libs/rs/rsComponent.cpp +++ b/libs/rs/rsComponent.cpp @@ -16,22 +16,23 @@ #include "rsComponent.h" +#ifndef ANDROID_RS_BUILD_FOR_HOST #include <GLES/gl.h> +#else +#include <OpenGL/gl.h> +#endif using namespace android; using namespace android::renderscript; -Component::Component() -{ +Component::Component() { set(RS_TYPE_NONE, RS_KIND_USER, false, 1); } -Component::~Component() -{ +Component::~Component() { } -void Component::set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize) -{ +void Component::set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize) { mType = dt; mKind = dk; mNormalized = norm; @@ -44,7 +45,7 @@ void Component::set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize) mIsSigned = false; mIsPixel = false; - switch(mKind) { + switch (mKind) { case RS_KIND_PIXEL_L: case RS_KIND_PIXEL_A: mIsPixel = true; @@ -70,7 +71,7 @@ void Component::set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize) break; } - switch(mType) { + switch (mType) { case RS_TYPE_NONE: return; case RS_TYPE_UNSIGNED_5_6_5: @@ -91,6 +92,26 @@ void Component::set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize) mNormalized = true; rsAssert(mKind == RS_KIND_PIXEL_RGBA); return; + + case RS_TYPE_MATRIX_4X4: + mTypeBits = 16 * 32; + rsAssert(mVectorSize == 1); + rsAssert(mNormalized == false); + rsAssert(mKind == RS_KIND_USER); + break; + case RS_TYPE_MATRIX_3X3: + mTypeBits = 9 * 32; + rsAssert(mVectorSize == 1); + rsAssert(mNormalized == false); + rsAssert(mKind == RS_KIND_USER); + break; + case RS_TYPE_MATRIX_2X2: + mTypeBits = 4 * 32; + rsAssert(mVectorSize == 1); + rsAssert(mNormalized == false); + rsAssert(mKind == RS_KIND_USER); + break; + case RS_TYPE_ELEMENT: case RS_TYPE_TYPE: case RS_TYPE_ALLOCATION: @@ -148,16 +169,20 @@ void Component::set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize) case RS_TYPE_UNSIGNED_64: mTypeBits = 64; break; + + case RS_TYPE_BOOLEAN: + mTypeBits = 8; + break; } mBits = mTypeBits * mVectorSize; } +bool Component::isReference() const { + return (mType >= RS_TYPE_ELEMENT); +} - - -uint32_t Component::getGLType() const -{ +uint32_t Component::getGLType() const { 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; @@ -175,8 +200,7 @@ uint32_t Component::getGLType() const return 0; } -uint32_t Component::getGLFormat() const -{ +uint32_t Component::getGLFormat() const { switch (mKind) { case RS_KIND_PIXEL_L: return GL_LUMINANCE; case RS_KIND_PIXEL_A: return GL_ALPHA; @@ -188,86 +212,9 @@ uint32_t Component::getGLFormat() const return 0; } -static const char * gCTypeStrings[] = { - 0, - 0,//"F16", - "float", - "double", - "char", - "short", - "int", - 0,//"S64", - "char",//U8", - "short",//U16", - "int",//U32", - 0,//"U64", - 0,//"UP_565", - 0,//"UP_5551", - 0,//"UP_4444", - 0,//"ELEMENT", - 0,//"TYPE", - 0,//"ALLOCATION", - 0,//"SAMPLER", - 0,//"SCRIPT", - 0,//"MESH", - 0,//"PROGRAM_FRAGMENT", - 0,//"PROGRAM_VERTEX", - 0,//"PROGRAM_RASTER", - 0,//"PROGRAM_STORE", -}; - -static const char * gCVecTypeStrings[] = { - 0, - 0,//"F16", - "vecF32", - "vecF64", - "vecI8", - "vecI16", - "vecI32", - 0,//"S64", - "vecU8",//U8", - "vecU16",//U16", - "vecU32",//U32", - 0,//"U64", - 0,//"UP_565", - 0,//"UP_5551", - 0,//"UP_4444", - 0,//"ELEMENT", - 0,//"TYPE", - 0,//"ALLOCATION", - 0,//"SAMPLER", - 0,//"SCRIPT", - 0,//"MESH", - 0,//"PROGRAM_FRAGMENT", - 0,//"PROGRAM_VERTEX", - 0,//"PROGRAM_RASTER", - 0,//"PROGRAM_STORE", -}; - -String8 Component::getCType() const -{ - char buf[64]; - if (mVectorSize == 1) { - return String8(gCTypeStrings[mType]); - } - - // Yuck, acc WAR - // Appears to have problems packing chars - if (mVectorSize == 4 && mType == RS_TYPE_UNSIGNED_8) { - return String8("int"); - } - - - String8 s(gCVecTypeStrings[mType]); - sprintf(buf, "_%i_t", mVectorSize); - s.append(buf); - return s; -} - -String8 Component::getGLSLType() const -{ +String8 Component::getGLSLType() const { if (mType == RS_TYPE_SIGNED_32) { - switch(mVectorSize) { + switch (mVectorSize) { case 1: return String8("int"); case 2: return String8("ivec2"); case 3: return String8("ivec3"); @@ -275,17 +222,26 @@ String8 Component::getGLSLType() const } } if (mType == RS_TYPE_FLOAT_32) { - switch(mVectorSize) { + switch (mVectorSize) { case 1: return String8("float"); case 2: return String8("vec2"); case 3: return String8("vec3"); case 4: return String8("vec4"); } } + if ((mType == RS_TYPE_MATRIX_4X4) && (mVectorSize == 1)) { + return String8("mat4"); + } + if ((mType == RS_TYPE_MATRIX_3X3) && (mVectorSize == 1)) { + return String8("mat3"); + } + if ((mType == RS_TYPE_MATRIX_2X2) && (mVectorSize == 1)) { + return String8("mat2"); + } return String8(); } -static const char * gTypeStrings[] = { +static const char * gTypeBasicStrings[] = { "NONE", "F16", "F32", @@ -298,9 +254,16 @@ static const char * gTypeStrings[] = { "U16", "U32", "U64", + "BOOLEAN", "UP_565", "UP_5551", "UP_4444", + "MATRIX_4X4", + "MATRIX_3X3", + "MATRIX_2X2", +}; + +static const char * gTypeObjStrings[] = { "ELEMENT", "TYPE", "ALLOCATION", @@ -328,10 +291,33 @@ static const char * gKindStrings[] = { "PIXEL_RGBA", }; -void Component::dumpLOGV(const char *prefix) const -{ - LOGV("%s Component: %s, %s, vectorSize=%i, bits=%i", - prefix, gTypeStrings[mType], gKindStrings[mKind], mVectorSize, mBits); +void Component::dumpLOGV(const char *prefix) const { + if (mType >= RS_TYPE_ELEMENT) { + LOGV("%s Component: %s, %s, vectorSize=%i, bits=%i", + prefix, gTypeObjStrings[mType - RS_TYPE_ELEMENT], gKindStrings[mKind], mVectorSize, mBits); + } else { + LOGV("%s Component: %s, %s, vectorSize=%i, bits=%i", + prefix, gTypeBasicStrings[mType], gKindStrings[mKind], mVectorSize, mBits); + } +} + +void Component::serialize(OStream *stream) const { + stream->addU8((uint8_t)mType); + stream->addU8((uint8_t)mKind); + stream->addU8((uint8_t)(mNormalized ? 1 : 0)); + stream->addU32(mVectorSize); } +void Component::loadFromStream(IStream *stream) { + mType = (RsDataType)stream->loadU8(); + mKind = (RsDataKind)stream->loadU8(); + uint8_t temp = stream->loadU8(); + mNormalized = temp != 0; + mVectorSize = stream->loadU32(); + + set(mType, mKind, mNormalized, mVectorSize); +} + + + diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h index 71de324..1bb4ff4 100644 --- a/libs/rs/rsComponent.h +++ b/libs/rs/rsComponent.h @@ -25,8 +25,7 @@ namespace renderscript { // An element is a group of Components that occupies one cell in a structure. -class Component -{ +class Component { public: Component(); ~Component(); @@ -35,7 +34,6 @@ public: uint32_t getGLType() const; uint32_t getGLFormat() const; - String8 getCType() const; String8 getGLSLType() const; void dumpLOGV(const char *prefix) const; @@ -48,6 +46,12 @@ public: bool getIsSigned() const {return mIsSigned;} uint32_t getBits() const {return mBits;} + // Helpers for reading / writing this class out + void serialize(OStream *stream) const; + void loadFromStream(IStream *stream); + + bool isReference() const; + protected: RsDataType mType; RsDataKind mKind; diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 90a2c79..40cb5c7 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -18,21 +18,24 @@ #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> +#include <sched.h> #include <cutils/properties.h> -#include <EGL/eglext.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> using namespace android; using namespace android::renderscript; @@ -41,6 +44,7 @@ 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) { @@ -54,23 +58,64 @@ static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { } } -void Context::initEGL(bool useGL2) -{ +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, GL_NONE, EGL_NONE }; - -#ifdef HAS_CONTEXT_PRIORITY -#ifdef EGL_IMG_context_priority -#warning "using EGL_IMG_context_priority" - if (mThreadPriority > 0) { - context_attribs2[2] = EGL_CONTEXT_PRIORITY_LEVEL_IMG; - context_attribs2[3] = EGL_CONTEXT_PRIORITY_LOW_IMG; - } -#endif -#endif + EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; memset(configAttribs, 0, sizeof(configAttribs)); @@ -78,15 +123,13 @@ void Context::initEGL(bool useGL2) configAttribsPtr[1] = EGL_WINDOW_BIT; configAttribsPtr += 2; - if (useGL2) { - configAttribsPtr[0] = EGL_RENDERABLE_TYPE; - configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; - configAttribsPtr += 2; - } + configAttribsPtr[0] = EGL_RENDERABLE_TYPE; + configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; + configAttribsPtr += 2; - if (mUseDepth) { + if (mUserSurfaceConfig.depthMin > 0) { configAttribsPtr[0] = EGL_DEPTH_SIZE; - configAttribsPtr[1] = 16; + configAttribsPtr[1] = mUserSurfaceConfig.depthMin; configAttribsPtr += 2; } @@ -99,38 +142,125 @@ void Context::initEGL(bool useGL2) configAttribsPtr[0] = EGL_NONE; rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint)))); - LOGV("initEGL start"); + LOGV("%p initEGL start", this); mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); checkEglError("eglGetDisplay"); eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion); checkEglError("eglInitialize"); - status_t err = EGLUtils::selectConfigForNativeWindow(mEGL.mDisplay, configAttribs, mWndSurface, &mEGL.mConfig); - if (err) { - LOGE("couldn't find an EGLConfig matching the screen format\n"); +#if 1 + PixelFormat pf = PIXEL_FORMAT_RGBA_8888; + if (mUserSurfaceConfig.alphaMin == 0) { + pf = PIXEL_FORMAT_RGBX_8888; } - //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs); - - if (useGL2) { - mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, context_attribs2); - } else { - mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL); + 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) { - LOGE("eglCreateContext returned 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"); + pthread_mutex_unlock(&gInitMutex); + deinitEGL(); + 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("deinitEGL"); - setSurface(0, 0, NULL); - eglDestroyContext(mEGL.mDisplay, mEGL.mContext); - checkEglError("eglDestroyContext"); +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) { @@ -138,105 +268,112 @@ void Context::deinitEGL() } } +Context::PushState::PushState(Context *con) { + mRsc = con; + mFragment.set(con->getProgramFragment()); + mVertex.set(con->getProgramVertex()); + mStore.set(con->getProgramStore()); + mRaster.set(con->getProgramRaster()); + mFont.set(con->getFont()); +} + +Context::PushState::~PushState() { + mRsc->setProgramFragment(mFragment.get()); + mRsc->setProgramVertex(mVertex.get()); + mRsc->setProgramStore(mStore.get()); + mRsc->setProgramRaster(mRaster.get()); + mRsc->setFont(mFont.get()); +} -uint32_t Context::runScript(Script *s, uint32_t launchID) -{ - ObjectBaseRef<ProgramFragment> frag(mFragment); - ObjectBaseRef<ProgramVertex> vtx(mVertex); - ObjectBaseRef<ProgramFragmentStore> store(mFragmentStore); - ObjectBaseRef<ProgramRaster> raster(mRaster); - uint32_t ret = s->run(this, launchID); +uint32_t Context::runScript(Script *s) { + PushState(this); - mFragment.set(frag); - mVertex.set(vtx); - mFragmentStore.set(store); - mRaster.set(raster); + uint32_t ret = s->run(this); return ret; } -void Context::checkError(const char *msg) const -{ +void Context::checkError(const char *msg, bool isFatal) const { + GLenum err = glGetError(); if (err != GL_NO_ERROR) { - LOGE("GL Error, 0x%x, from %s", err, msg); + 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() -{ - timerSet(RS_TIMER_CLEAR_SWAP); - rsAssert(mRootScript->mEnviroment.mIsRoot); - - eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth); - eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight); - glViewport(0, 0, mEGL.mWidth, mEGL.mHeight); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - glClearColor(mRootScript->mEnviroment.mClearColor[0], - mRootScript->mEnviroment.mClearColor[1], - mRootScript->mEnviroment.mClearColor[2], - mRootScript->mEnviroment.mClearColor[3]); - if (mUseDepth) { - glDepthMask(GL_TRUE); - glClearDepthf(mRootScript->mEnviroment.mClearDepth); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } else { - glClear(GL_COLOR_BUFFER_BIT); - } +uint32_t Context::runRootScript() { + glViewport(0, 0, mWidth, mHeight); timerSet(RS_TIMER_SCRIPT); mStateFragmentStore.mLast.clear(); - uint32_t ret = runScript(mRootScript.get(), 0); + uint32_t ret = runScript(mRootScript.get()); checkError("runRootScript"); - if (mError != RS_ERROR_NONE) { - // If we have an error condition we stop rendering until - // somthing changes that might fix it. - ret = 0; - } return ret; } -uint64_t Context::getTime() const -{ +uint64_t Context::getTime() const { struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000); } -void Context::timerReset() -{ +void Context::timerReset() { for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) { mTimers[ct] = 0; } } -void Context::timerInit() -{ +void Context::timerInit() { mTimeLast = getTime(); mTimeFrame = mTimeLast; mTimeLastFrame = mTimeLast; mTimerActive = RS_TIMER_INTERNAL; + mAverageFPSFrameCount = 0; + mAverageFPSStartTime = mTimeLast; + mAverageFPS = 0; timerReset(); } -void Context::timerFrame() -{ +void Context::timerFrame() { mTimeLastFrame = mTimeFrame; mTimeFrame = getTime(); + // Update average fps + const uint64_t averageFramerateInterval = 1000 * 1000000; + mAverageFPSFrameCount ++; + uint64_t inverval = mTimeFrame - mAverageFPSStartTime; + if (inverval >= averageFramerateInterval) { + inverval = inverval / 1000000; + mAverageFPS = (mAverageFPSFrameCount * 1000) / inverval; + mAverageFPSFrameCount = 0; + mAverageFPSStartTime = mTimeFrame; + } } -void Context::timerSet(Timers tm) -{ +void Context::timerSet(Timers tm) { uint64_t last = mTimeLast; mTimeLast = getTime(); mTimers[mTimerActive] += mTimeLast - last; mTimerActive = tm; } -void Context::timerPrint() -{ +void Context::timerPrint() { double total = 0; for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) { total += mTimers[ct]; @@ -248,46 +385,57 @@ void Context::timerPrint() if (props.mLogTimes) { - LOGV("RS: Frame (%i), Script %2.1f (%i), Clear & Swap %2.1f (%i), Idle %2.1f (%lli), Internal %2.1f (%lli)", + LOGV("RS: Frame (%i), Script %2.1f%% (%i), Swap %2.1f%% (%i), Idle %2.1f%% (%lli), Internal %2.1f%% (%lli), Avg fps: %u", mTimeMSLastFrame, 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript, 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap, 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000, - 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000); + 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000, + mAverageFPS); } } -bool Context::setupCheck() -{ - if (checkVersion2_0()) { - 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); - - } else { - mFragmentStore->setupGL(this, &mStateFragmentStore); - mFragment->setupGL(this, &mStateFragment); - mRaster->setupGL(this, &mStateRaster); - mVertex->setupGL(this, &mStateVertex); +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); return true; } -static bool getProp(const char *str) -{ +void Context::setupProgramStore() { + mFragmentStore->setupGL2(this, &mStateFragmentStore); +} + +static bool getProp(const char *str) { char buf[PROPERTY_VALUE_MAX]; property_get(str, buf, "0"); return 0 != strcmp(buf, "0"); } -void * Context::threadProc(void *vrsc) -{ +void Context::displayDebugStats() { + char buffer[128]; + sprintf(buffer, "Avg fps %u, Frame %i ms, Script %i ms", mAverageFPS, mTimeMSLastFrame, mTimeMSLastScript); + float oldR, oldG, oldB, oldA; + mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA); + uint32_t bufferLen = strlen(buffer); + + float shadowCol = 0.1f; + mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f); + mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6); + + mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f); + mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7); + + mStateFont.setFontColor(oldR, oldG, oldB, oldA); +} + +void * Context::threadProc(void *vrsc) { Context *rsc = static_cast<Context *>(vrsc); rsc->mNativeThreadId = gettid(); @@ -298,28 +446,39 @@ void * Context::threadProc(void *vrsc) 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"); - ScriptTLSStruct *tlsStruct = new ScriptTLSStruct; - if (!tlsStruct) { + 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; } - tlsStruct->mContext = rsc; - tlsStruct->mScript = NULL; - int status = pthread_setspecific(rsc->gThreadTLSKey, tlsStruct); + 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->mEGL.mWidth, rsc->mEGL.mHeight); - rsc->setRaster(NULL); - rsc->mStateVertex.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight); - rsc->setVertex(NULL); - rsc->mStateFragment.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight); - rsc->setFragment(NULL); - rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight); - rsc->setFragmentStore(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->mStateVertexArray.init(rsc); } @@ -333,6 +492,11 @@ void * Context::threadProc(void *vrsc) 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); @@ -341,10 +505,7 @@ void * Context::threadProc(void *vrsc) rsc->timerPrint(); rsc->timerReset(); } - if (rsc->mObjDestroy.mNeedToEmpty) { - rsc->objDestroyOOBRun(); - } - if (rsc->mThreadPriority > 0 && targetTime) { + if (targetTime > 1) { int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000; if (t > 0) { usleep(t); @@ -352,35 +513,91 @@ void * Context::threadProc(void *vrsc) } } - LOGV("RS Thread exiting"); - if (rsc->mIsGraphicsContext) { - rsc->mRaster.clear(); - rsc->mFragment.clear(); - rsc->mVertex.clear(); - rsc->mFragmentStore.clear(); - rsc->mRootScript.clear(); - rsc->mStateRaster.deinit(rsc); - rsc->mStateVertex.deinit(rsc); - rsc->mStateFragment.deinit(rsc); - rsc->mStateFragmentStore.deinit(rsc); - } - ObjectBase::zeroAllUserRef(rsc); - - rsc->mObjDestroy.mNeedToEmpty = true; - rsc->objDestroyOOBRun(); + 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; +} + +void Context::destroyWorkerThreadResources() { + //LOGV("destroyWorkerThreadResources 1"); + if (mIsGraphicsContext) { + mRaster.clear(); + mFragment.clear(); + mVertex.clear(); + mFragmentStore.clear(); + mFont.clear(); + mRootScript.clear(); + mStateRaster.deinit(this); + mStateVertex.deinit(this); + mStateFragment.deinit(this); + mStateFragmentStore.deinit(this); + mStateFont.deinit(this); + mShaderCache.cleanupAll(); + } + ObjectBase::zeroAllUserRef(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 Thread exited"); + //LOGV("RS helperThread exited %p idx=%i", rsc, idx); return NULL; } -void Context::setPriority(int32_t p) -{ +void Context::launchThreads(WorkerCallback_t cbk, void *data) { + mWorkers.mLaunchData = data; + mWorkers.mLaunchCallback = cbk; + mWorkers.mRunningCount = (int)mWorkers.mCount; + for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { + mWorkers.mLaunchSignals[ct].set(); + } + while (mWorkers.mRunningCount) { + 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. // This is probably not what we want for something the user is actively @@ -395,27 +612,45 @@ void Context::setPriority(int32_t p) // success; reset the priority as well } #else - setpriority(PRIO_PROCESS, mNativeThreadId, p); + setpriority(PRIO_PROCESS, mNativeThreadId, p); + for (uint32_t ct=0; ct < mWorkers.mCount; ct++) { + setpriority(PRIO_PROCESS, mWorkers.mNativeThreadId[ct], p); + } #endif } -Context::Context(Device *dev, bool isGraphics, bool useDepth) -{ - pthread_mutex_lock(&gInitMutex); - - dev->addContext(this); - mDev = dev; +Context::Context() { + mDev = NULL; mRunning = false; mExit = false; - mUseDepth = useDepth; mPaused = false; mObjHead = NULL; mError = RS_ERROR_NONE; - mErrorMsg = NULL; +} + +Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc) { + Context * rsc = new Context(); + if (!rsc->initContext(dev, sc)) { + delete rsc; + return NULL; + } + return rsc; +} + +bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) { + pthread_mutex_lock(&gInitMutex); + + dev->addContext(this); + mDev = dev; + if (sc) { + mUserSurfaceConfig = *sc; + } else { + memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig)); + } memset(&mEGL, 0, sizeof(mEGL)); memset(&mGL, 0, sizeof(mGL)); - mIsGraphicsContext = isGraphics; + mIsGraphicsContext = sc != NULL; int status; pthread_attr_t threadAttr; @@ -425,10 +660,11 @@ Context::Context(Device *dev, bool isGraphics, bool useDepth) if (status) { LOGE("Failed to init thread tls key."); pthread_mutex_unlock(&gInitMutex); - return; + return false; } } gThreadTLSKeyCount++; + pthread_mutex_unlock(&gInitMutex); // Global init done at this point. @@ -436,39 +672,74 @@ Context::Context(Device *dev, bool isGraphics, bool useDepth) status = pthread_attr_init(&threadAttr); if (status) { LOGE("Failed to init thread attribute."); - return; + return false; } mWndSurface = NULL; - objDestroyOOBInit(); timerInit(); timerSet(RS_TIMER_INTERNAL); - LOGV("RS Launching thread"); + 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."); + return false; } - - while(!mRunning) { + while (!mRunning && (mError == RS_ERROR_NONE)) { usleep(100); } + if (mError != RS_ERROR_NONE) { + return false; + } + + mWorkers.mCompleteSignal.init(); + mWorkers.mRunningCount = 0; + mWorkers.mLaunchCount = 0; + 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; + } + } pthread_attr_destroy(&threadAttr); + return true; } -Context::~Context() -{ +Context::~Context() { LOGV("Context::~Context"); + + mIO.mToCore.flush(); + rsAssert(mExit); mExit = true; mPaused = false; void *res; mIO.shutdown(); int status = pthread_join(mThreadId, &res); - mObjDestroy.mNeedToEmpty = true; - objDestroyOOBRun(); + + // Cleanup compute threads. + mWorkers.mLaunchData = NULL; + mWorkers.mLaunchCallback = NULL; + mWorkers.mRunningCount = (int)mWorkers.mCount; + for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { + mWorkers.mLaunchSignals[ct].set(); + } + for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { + int status = pthread_join(mWorkers.mThreadId[ct], &res); + } + rsAssert(!mWorkers.mRunningCount); // Global structure cleanup. pthread_mutex_lock(&gInitMutex); @@ -481,38 +752,31 @@ Context::~Context() mDev = NULL; } pthread_mutex_unlock(&gInitMutex); - - objDestroyOOBDestroy(); + LOGV("Context::~Context done"); } -void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) -{ +void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) { rsAssert(mIsGraphicsContext); EGLBoolean ret; - if (mEGL.mSurface != NULL) { - ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + // 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; - mEGL.mWidth = 0; - mEGL.mHeight = 0; - mWidth = 0; - mHeight = 0; + mWidth = 1; + mHeight = 1; } mWndSurface = sur; if (mWndSurface != NULL) { - bool first = false; - if (!mEGL.mContext) { - first = true; - pthread_mutex_lock(&gInitMutex); - initEGL(true); - pthread_mutex_unlock(&gInitMutex); - } + mWidth = w; + mHeight = h; mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL); checkEglError("eglCreateWindowSurface"); @@ -523,81 +787,26 @@ void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext); checkEglError("eglMakeCurrent", ret); - eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth); - eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight); - mWidth = w; - mHeight = h; - mStateVertex.updateSize(this, w, h); - - if ((int)mWidth != mEGL.mWidth || (int)mHeight != mEGL.mHeight) { - LOGE("EGL/Surface mismatch EGL (%i x %i) SF (%i x %i)", mEGL.mWidth, mEGL.mHeight, mWidth, mHeight); - } - - if (first) { - 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"); - } 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"); - } - + mStateVertex.updateSize(this); } } -void Context::pause() -{ +void Context::pause() { rsAssert(mIsGraphicsContext); mPaused = true; } -void Context::resume() -{ +void Context::resume() { rsAssert(mIsGraphicsContext); mPaused = false; } -void Context::setRootScript(Script *s) -{ +void Context::setRootScript(Script *s) { rsAssert(mIsGraphicsContext); mRootScript.set(s); } -void Context::setFragmentStore(ProgramFragmentStore *pfs) -{ +void Context::setProgramStore(ProgramStore *pfs) { rsAssert(mIsGraphicsContext); if (pfs == NULL) { mFragmentStore.set(mStateFragmentStore.mDefault); @@ -606,8 +815,7 @@ void Context::setFragmentStore(ProgramFragmentStore *pfs) } } -void Context::setFragment(ProgramFragment *pf) -{ +void Context::setProgramFragment(ProgramFragment *pf) { rsAssert(mIsGraphicsContext); if (pf == NULL) { mFragment.set(mStateFragment.mDefault); @@ -616,8 +824,7 @@ void Context::setFragment(ProgramFragment *pf) } } -void Context::setRaster(ProgramRaster *pr) -{ +void Context::setProgramRaster(ProgramRaster *pr) { rsAssert(mIsGraphicsContext); if (pr == NULL) { mRaster.set(mStateRaster.mDefault); @@ -626,8 +833,7 @@ void Context::setRaster(ProgramRaster *pr) } } -void Context::setVertex(ProgramVertex *pv) -{ +void Context::setProgramVertex(ProgramVertex *pv) { rsAssert(mIsGraphicsContext); if (pv == NULL) { mVertex.set(mStateVertex.mDefault); @@ -636,16 +842,23 @@ void Context::setVertex(ProgramVertex *pv) } } -void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) -{ +void Context::setFont(Font *f) { + rsAssert(mIsGraphicsContext); + if (f == NULL) { + mFont.set(mStateFont.mDefault); + } else { + mFont.set(f); + } +} + +void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) { rsAssert(!obj->getName()); obj->setName(name, len); mNames.add(obj); } -void Context::removeName(ObjectBase *obj) -{ - for(size_t ct=0; ct < mNames.size(); ct++) { +void Context::removeName(ObjectBase *obj) { + for (size_t ct=0; ct < mNames.size(); ct++) { if (obj == mNames[ct]) { mNames.removeAt(ct); return; @@ -653,174 +866,100 @@ void Context::removeName(ObjectBase *obj) } } -ObjectBase * Context::lookupName(const char *name) const -{ - for(size_t ct=0; ct < mNames.size(); ct++) { - if (!strcmp(name, mNames[ct]->getName())) { - return mNames[ct]; - } +RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID, bool wait) { + *receiveLen = 0; + if (!wait && mIO.mToClient.isEmpty()) { + return RS_MESSAGE_TO_CLIENT_NONE; } - return NULL; -} - -void Context::appendNameDefines(String8 *str) const -{ - char buf[256]; - for (size_t ct=0; ct < mNames.size(); ct++) { - str->append("#define NAMED_"); - str->append(mNames[ct]->getName()); - str->append(" "); - sprintf(buf, "%i\n", (int)mNames[ct]); - str->append(buf); - } -} - -bool Context::objDestroyOOBInit() -{ - int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL); - if (status) { - LOGE("Context::ObjDestroyOOBInit mutex init failure"); - return false; - } - return true; -} - -void Context::objDestroyOOBRun() -{ - if (mObjDestroy.mNeedToEmpty) { - int status = pthread_mutex_lock(&mObjDestroy.mMutex); - if (status) { - LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status); - return; - } - - for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) { - mObjDestroy.mDestroyList[ct]->decUserRef(); - } - mObjDestroy.mDestroyList.clear(); - mObjDestroy.mNeedToEmpty = false; - - status = pthread_mutex_unlock(&mObjDestroy.mMutex); - if (status) { - LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status); - } - } -} - -void Context::objDestroyOOBDestroy() -{ - rsAssert(!mObjDestroy.mNeedToEmpty); - pthread_mutex_destroy(&mObjDestroy.mMutex); -} -void Context::objDestroyAdd(ObjectBase *obj) -{ - int status = pthread_mutex_lock(&mObjDestroy.mMutex); - if (status) { - LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status); - return; - } - - mObjDestroy.mNeedToEmpty = true; - mObjDestroy.mDestroyList.add(obj); - - status = pthread_mutex_unlock(&mObjDestroy.mMutex); - if (status) { - LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status); + 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; } -uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait) -{ +RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait) { //LOGE("getMessageToClient %i %i", bufferLen, wait); - if (!wait) { - if (mIO.mToClient.isEmpty()) { - // No message to get and not going to wait for one. - receiveLen = 0; - return 0; - } + *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 void *d = mIO.mToClient.get(&commandID, &bytesData); + const uint32_t *d = (const uint32_t *)mIO.mToClient.get(&commandID, &bytesData); //LOGE("getMessageToClient 3 %i %i", commandID, bytesData); - *receiveLen = bytesData; + *receiveLen = bytesData - sizeof(uint32_t); + *subID = d[0]; + + //LOGE("getMessageToClient %i %i", commandID, *subID); if (bufferLen >= bytesData) { - memcpy(data, d, bytesData); + memcpy(data, d+1, *receiveLen); mIO.mToClient.next(); - return commandID; + return (RsMessageToClientType)commandID; } - return 0; + return RS_MESSAGE_TO_CLIENT_RESIZE; } -bool Context::sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace) -{ - //LOGE("sendMessageToClient %i %i %i", cmdID, len, waitForSpace); +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.getFreeSpace() < len) { + if (!mIO.mToClient.makeSpaceNonBlocking(len + 12)) { // Not enough room, and not waiting. return false; } } //LOGE("sendMessageToClient 2"); - void *p = mIO.mToClient.reserve(len); - memcpy(p, data, len); - mIO.mToClient.commit(cmdID, len); + 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; } -void Context::initToClient() -{ - while(!mRunning) { +void Context::initToClient() { + while (!mRunning) { usleep(100); } } -void Context::deinitToClient() -{ +void Context::deinitToClient() { mIO.mToClient.shutdown(); } -const char * Context::getError(RsError *err) -{ - *err = mError; - mError = RS_ERROR_NONE; - if (*err != RS_ERROR_NONE) { - return mErrorMsg; - } - return NULL; -} - -void Context::setError(RsError e, const char *msg) -{ +void Context::setError(RsError e, const char *msg) const { mError = e; - mErrorMsg = msg; + sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true); } -void Context::dumpDebug() const -{ +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, w=%i h=%i Display=%p", mEGL.mContext, - mEGL.mSurface, mEGL.mWidth, mEGL.mHeight, mEGL.mDisplay); + 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, useDepth %i, paused %i", mRunning, mExit, mUseDepth, mPaused); + 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); @@ -835,15 +974,15 @@ void Context::dumpDebug() const namespace android { namespace renderscript { +void rsi_ContextFinish(Context *rsc) { +} -void rsi_ContextBindRootScript(Context *rsc, RsScript vs) -{ +void rsi_ContextBindRootScript(Context *rsc, RsScript vs) { Script *s = static_cast<Script *>(vs); rsc->setRootScript(s); } -void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) -{ +void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) { Sampler *s = static_cast<Sampler *>(vs); if (slot > RS_MAX_SAMPLER_SLOT) { @@ -854,124 +993,115 @@ void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) s->bindToContext(&rsc->mStateSampler, slot); } -void rsi_ContextBindProgramFragmentStore(Context *rsc, RsProgramFragmentStore vpfs) -{ - ProgramFragmentStore *pfs = static_cast<ProgramFragmentStore *>(vpfs); - rsc->setFragmentStore(pfs); +void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) { + ProgramStore *pfs = static_cast<ProgramStore *>(vpfs); + rsc->setProgramStore(pfs); } -void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) -{ +void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) { ProgramFragment *pf = static_cast<ProgramFragment *>(vpf); - rsc->setFragment(pf); + rsc->setProgramFragment(pf); } -void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) -{ +void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) { ProgramRaster *pr = static_cast<ProgramRaster *>(vpr); - rsc->setRaster(pr); + rsc->setProgramRaster(pr); } -void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) -{ +void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) { ProgramVertex *pv = static_cast<ProgramVertex *>(vpv); - rsc->setVertex(pv); + rsc->setProgramVertex(pv); +} + +void rsi_ContextBindFont(Context *rsc, RsFont vfont) { + Font *font = static_cast<Font *>(vfont); + rsc->setFont(font); } -void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len) -{ +void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len) { ObjectBase *ob = static_cast<ObjectBase *>(obj); rsc->assignName(ob, name, len); } -void rsi_ObjDestroy(Context *rsc, void *obj) -{ - ObjectBase *ob = static_cast<ObjectBase *>(obj); +void rsi_ObjDestroy(Context *rsc, void *optr) { + ObjectBase *ob = static_cast<ObjectBase *>(optr); rsc->removeName(ob); ob->decUserRef(); } -void rsi_ContextPause(Context *rsc) -{ +void rsi_ContextPause(Context *rsc) { rsc->pause(); } -void rsi_ContextResume(Context *rsc) -{ +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, ANativeWindow *sur) { rsc->setSurface(w, h, sur); } -void rsi_ContextSetPriority(Context *rsc, int32_t p) -{ +void rsi_ContextSetPriority(Context *rsc, int32_t p) { rsc->setPriority(p); } -void rsi_ContextDump(Context *rsc, int32_t bits) -{ +void rsi_ContextDump(Context *rsc, int32_t bits) { ObjectBase::dumpAll(rsc); } -const char * rsi_ContextGetError(Context *rsc, RsError *e) -{ - const char *msg = rsc->getError(e); - if (*e != RS_ERROR_NONE) { - LOGE("RS Error %i %s", *e, msg); - } - return msg; +void rsi_ContextDestroyWorker(Context *rsc) { + rsc->destroyWorkerThreadResources();; } } } +void rsContextDestroy(RsContext vcon) { + LOGV("rsContextDestroy %p", vcon); + Context *rsc = static_cast<Context *>(vcon); + rsContextDestroyWorker(rsc); + delete rsc; + LOGV("rsContextDestroy 2 %p", vcon); +} -RsContext rsContextCreate(RsDevice vdev, uint32_t version) -{ +RsContext rsContextCreate(RsDevice vdev, uint32_t version) { LOGV("rsContextCreate %p", vdev); Device * dev = static_cast<Device *>(vdev); - Context *rsc = new Context(dev, false, false); + Context *rsc = Context::createContext(dev, NULL); return rsc; } -RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, bool useDepth) -{ - LOGV("rsContextCreateGL %p, %i", vdev, useDepth); +RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, RsSurfaceConfig sc) { + LOGV("rsContextCreateGL %p", vdev); Device * dev = static_cast<Device *>(vdev); - Context *rsc = new Context(dev, true, useDepth); + Context *rsc = Context::createContext(dev, &sc); + LOGV("rsContextCreateGL ret %p ", rsc); return rsc; } -void rsContextDestroy(RsContext vrsc) -{ +RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait) { Context * rsc = static_cast<Context *>(vrsc); - delete rsc; + return rsc->peekMessageToClient(receiveLen, subID, wait); } -void rsObjDestroyOOB(RsContext vrsc, void *obj) -{ +RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait) { Context * rsc = static_cast<Context *>(vrsc); - rsc->objDestroyAdd(static_cast<ObjectBase *>(obj)); + return rsc->getMessageToClient(data, receiveLen, subID, bufferLen, wait); } -uint32_t rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, size_t bufferLen, bool wait) -{ - Context * rsc = static_cast<Context *>(vrsc); - return rsc->getMessageToClient(data, receiveLen, bufferLen, wait); -} - -void rsContextInitToClient(RsContext vrsc) -{ +void rsContextInitToClient(RsContext vrsc) { Context * rsc = static_cast<Context *>(vrsc); rsc->initToClient(); } -void rsContextDeinitToClient(RsContext vrsc) -{ +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) { + ObjectBase *ob = static_cast<ObjectBase *>(obj); + (*name) = ob->getName(); +} diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index e24fd09..9f94f26 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -18,21 +18,21 @@ #define ANDROID_RS_CONTEXT_H #include "rsUtils.h" +#include "rsMutex.h" #include "rsThreadIO.h" #include "rsType.h" #include "rsMatrix.h" #include "rsAllocation.h" -#include "rsSimpleMesh.h" #include "rsMesh.h" #include "rsDevice.h" #include "rsScriptC.h" #include "rsAllocation.h" #include "rsAdapter.h" #include "rsSampler.h" -#include "rsLight.h" +#include "rsFont.h" #include "rsProgramFragment.h" -#include "rsProgramFragmentStore.h" +#include "rsProgramStore.h" #include "rsProgramRaster.h" #include "rsProgramVertex.h" #include "rsShaderCache.h" @@ -48,67 +48,106 @@ namespace android { namespace renderscript { -class Context -{ +#if 0 +#define CHECK_OBJ(o) { \ + GET_TLS(); \ + if (!ObjectBase::isValid(rsc, (const ObjectBase *)o)) { \ + LOGE("Bad object %p at %s, %i", o, __FILE__, __LINE__); \ + } \ +} +#define CHECK_OBJ_OR_NULL(o) { \ + GET_TLS(); \ + if (o && !ObjectBase::isValid(rsc, (const ObjectBase *)o)) { \ + LOGE("Bad object %p at %s, %i", o, __FILE__, __LINE__); \ + } \ +} +#else +#define CHECK_OBJ(o) +#define CHECK_OBJ_OR_NULL(o) +#endif + +class Context { public: - Context(Device *, bool isGraphics, bool useDepth); + static Context * createContext(Device *, const RsSurfaceConfig *sc); ~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 *); + ~PushState(); + + private: + ObjectBaseRef<ProgramFragment> mFragment; + ObjectBaseRef<ProgramVertex> mVertex; + ObjectBaseRef<ProgramStore> mStore; + ObjectBaseRef<ProgramRaster> mRaster; + ObjectBaseRef<Font> mFont; + Context *mRsc; + }; + + ScriptTLSStruct *mTlsStruct; + RsSurfaceConfig mUserSurfaceConfig; + + typedef void (*WorkerCallback_t)(void *usr, uint32_t idx); //StructuredAllocationContext mStateAllocation; ElementState mStateElement; TypeState mStateType; SamplerState mStateSampler; ProgramFragmentState mStateFragment; - ProgramFragmentStoreState mStateFragmentStore; + ProgramStoreState mStateFragmentStore; ProgramRasterState mStateRaster; ProgramVertexState mStateVertex; - LightState mStateLight; VertexArrayState mStateVertexArray; + FontState mStateFont; ScriptCState mScriptC; ShaderCache mShaderCache; void swapBuffers(); void setRootScript(Script *); - void setRaster(ProgramRaster *); - void setVertex(ProgramVertex *); - void setFragment(ProgramFragment *); - void setFragmentStore(ProgramFragmentStore *); + void setProgramRaster(ProgramRaster *); + void setProgramVertex(ProgramVertex *); + void setProgramFragment(ProgramFragment *); + void setProgramStore(ProgramStore *); + void setFont(Font *); void updateSurface(void *sur); - const ProgramFragment * getFragment() {return mFragment.get();} - const ProgramFragmentStore * getFragmentStore() {return mFragmentStore.get();} - const ProgramRaster * getRaster() {return mRaster.get();} - const ProgramVertex * getVertex() {return mVertex.get();} + ProgramFragment * getProgramFragment() {return mFragment.get();} + ProgramStore * getProgramStore() {return mFragmentStore.get();} + ProgramRaster * getProgramRaster() {return mRaster.get();} + ProgramVertex * getProgramVertex() {return mVertex.get();} + Font * getFont() {return mFont.get();} bool setupCheck(); - bool checkDriver() const {return mEGL.mSurface != 0;} + void setupProgramStore(); void pause(); void resume(); void setSurface(uint32_t w, uint32_t h, ANativeWindow *sur); void setPriority(int32_t p); + void destroyWorkerThreadResources(); void assignName(ObjectBase *obj, const char *name, uint32_t len); void removeName(ObjectBase *obj); - ObjectBase * lookupName(const char *name) const; - void appendNameDefines(String8 *str) const; - uint32_t getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait); - bool sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace); - uint32_t runScript(Script *s, uint32_t launchID); + 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); + bool sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace) const; + uint32_t runScript(Script *s); void initToClient(); void deinitToClient(); @@ -119,19 +158,20 @@ public: ProgramVertex * getDefaultProgramVertex() const { return mStateVertex.mDefault.get(); } - ProgramFragmentStore * getDefaultProgramFragmentStore() const { + ProgramStore * getDefaultProgramStore() const { return mStateFragmentStore.mDefault.get(); } ProgramRaster * getDefaultProgramRaster() const { return mStateRaster.mDefault.get(); } + Font* getDefaultFont() const { + return mStateFont.mDefault.get(); + } - uint32_t getWidth() const {return mEGL.mWidth;} - uint32_t getHeight() const {return mEGL.mHeight;} - + uint32_t getWidth() const {return mWidth;} + uint32_t getHeight() const {return mHeight;} - ThreadIO mIO; - void objDestroyAdd(ObjectBase *); + mutable ThreadIO mIO; // Timers enum Timers { @@ -148,25 +188,33 @@ public: void timerPrint(); void timerFrame(); - bool checkVersion1_1() const {return (mGL.mMajorVersion > 1) || (mGL.mMinorVersion >= 1); } - bool checkVersion2_0() const {return mGL.mMajorVersion >= 2; } - struct { bool mLogTimes; bool mLogScripts; bool mLogObjects; bool mLogShaders; + bool mLogShadersAttr; + bool mLogShadersUniforms; + bool mLogVisual; } props; void dumpDebug() const; - void checkError(const char *) const; - const char * getError(RsError *); - void setError(RsError e, const char *msg); + 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;} protected: Device *mDev; @@ -178,8 +226,7 @@ protected: EGLConfig mConfig; EGLContext mContext; EGLSurface mSurface; - EGLint mWidth; - EGLint mHeight; + EGLSurface mSurfaceDefault; EGLDisplay mDisplay; } mEGL; @@ -204,6 +251,8 @@ protected: bool OES_texture_npot; bool GL_IMG_texture_npot; + bool GL_NV_texture_npot_2D_mipmap; + float EXT_texture_max_aniso; } mGL; uint32_t mWidth; @@ -213,40 +262,47 @@ protected: bool mRunning; bool mExit; - bool mUseDepth; bool mPaused; - RsError mError; - const char *mErrorMsg; + mutable RsError mError; 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; - ObjectBaseRef<ProgramFragmentStore> mFragmentStore; + ObjectBaseRef<ProgramStore> mFragmentStore; ObjectBaseRef<ProgramRaster> mRaster; + ObjectBaseRef<Font> mFont; - - struct ObjDestroyOOB { - pthread_mutex_t mMutex; - Vector<ObjectBase *> mDestroyList; - bool mNeedToEmpty; - }; - ObjDestroyOOB mObjDestroy; - bool objDestroyOOBInit(); - void objDestroyOOBRun(); - void objDestroyOOBDestroy(); + void displayDebugStats(); private: Context(); + bool initContext(Device *, const RsSurfaceConfig *sc); + - void initEGL(bool useGL2); + bool initGLThread(); void deinitEGL(); uint32_t runRootScript(); static void * threadProc(void *); + static void * helperThreadProc(void *); ANativeWindow *mWndSurface; @@ -260,6 +316,9 @@ private: uint32_t mTimeMSLastFrame; uint32_t mTimeMSLastScript; uint32_t mTimeMSLastSwap; + uint32_t mAverageFPSFrameCount; + uint64_t mAverageFPSStartTime; + uint32_t mAverageFPS; }; } diff --git a/libs/rs/rsContextHostStub.h b/libs/rs/rsContextHostStub.h new file mode 100644 index 0000000..8cfb38b --- /dev/null +++ b/libs/rs/rsContextHostStub.h @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#ifndef ANDROID_RS_CONTEXT_HOST_STUB_H +#define ANDROID_RS_CONTEXT_HOST_STUB_H + +#include "rsUtils.h" +//#include "rsMutex.h" + +//#include "rsThreadIO.h" +#include "rsType.h" +#include "rsMatrix.h" +#include "rsAllocation.h" +#include "rsMesh.h" +//#include "rsDevice.h" +#include "rsScriptC.h" +#include "rsAllocation.h" +#include "rsAdapter.h" +#include "rsSampler.h" +#include "rsProgramFragment.h" +#include "rsProgramStore.h" +#include "rsProgramRaster.h" +#include "rsProgramVertex.h" +#include "rsShaderCache.h" +#include "rsVertexArray.h" + +//#include "rsgApiStructs.h" +//#include "rsLocklessFifo.h" + +//#include <ui/egl/android_natives.h> + +// --------------------------------------------------------------------------- +namespace android { +namespace renderscript { + +class Device; + +class Context { +public: + Context(Device *, bool isGraphics, bool useDepth) { + mObjHead = NULL; + } + ~Context() { + } + + + //StructuredAllocationContext mStateAllocation; + ElementState mStateElement; + TypeState mStateType; + SamplerState mStateSampler; + //ProgramFragmentState mStateFragment; + ProgramStoreState mStateFragmentStore; + //ProgramRasterState mStateRaster; + //ProgramVertexState mStateVertex; + VertexArrayState mStateVertexArray; + + //ScriptCState mScriptC; + ShaderCache mShaderCache; + + RsSurfaceConfig mUserSurfaceConfig; + + //bool setupCheck(); + + ProgramFragment * getDefaultProgramFragment() const { + return NULL; + } + ProgramVertex * getDefaultProgramVertex() const { + return NULL; + } + ProgramStore * getDefaultProgramStore() const { + return NULL; + } + ProgramRaster * getDefaultProgramRaster() const { + return NULL; + } + + uint32_t getWidth() const {return 0;} + uint32_t getHeight() const {return 0;} + + // Timers + enum Timers { + RS_TIMER_IDLE, + RS_TIMER_INTERNAL, + RS_TIMER_SCRIPT, + RS_TIMER_CLEAR_SWAP, + _RS_TIMER_TOTAL + }; + + bool checkVersion1_1() const {return false; } + bool checkVersion2_0() const {return false; } + + struct { + bool mLogTimes; + bool mLogScripts; + bool mLogObjects; + bool mLogShaders; + bool mLogShadersAttr; + bool mLogShadersUniforms; + bool mLogVisual; + } props; + + void dumpDebug() const { } + void checkError(const char *) const { }; + void setError(RsError e, const char *msg = NULL) { } + + mutable const ObjectBase * mObjHead; + + bool ext_OES_texture_npot() const {return mGL.OES_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;} + +protected: + + 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_NV_texture_npot_2D_mipmap; + float EXT_texture_max_aniso; + } mGL; + +}; + +} +} +#endif diff --git a/libs/rs/rsDevice.cpp b/libs/rs/rsDevice.cpp index b670ad4..dd96445 100644 --- a/libs/rs/rsDevice.cpp +++ b/libs/rs/rsDevice.cpp @@ -15,29 +15,27 @@ */ #include "rsDevice.h" +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif using namespace android; using namespace android::renderscript; -Device::Device() -{ +Device::Device() { mForceSW = false; - } -Device::~Device() -{ - +Device::~Device() { } -void Device::addContext(Context *rsc) -{ - mContexts.add(rsc); +void Device::addContext(Context *rsc) { + mContexts.push(rsc); } -void Device::removeContext(Context *rsc) -{ +void Device::removeContext(Context *rsc) { for (size_t idx=0; idx < mContexts.size(); idx++) { if (mContexts[idx] == rsc) { mContexts.removeAt(idx); @@ -46,23 +44,17 @@ void Device::removeContext(Context *rsc) } } - - -RsDevice rsDeviceCreate() -{ +RsDevice rsDeviceCreate() { Device * d = new Device(); return d; } -void rsDeviceDestroy(RsDevice dev) -{ +void rsDeviceDestroy(RsDevice dev) { Device * d = static_cast<Device *>(dev); delete d; - } -void rsDeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value) -{ +void rsDeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value) { Device * d = static_cast<Device *>(dev); if (p == RS_DEVICE_PARAM_FORCE_SOFTWARE_GL) { d->mForceSW = value != 0; diff --git a/libs/rs/rsDevice.h b/libs/rs/rsDevice.h index a8a4e77..ffb514b 100644 --- a/libs/rs/rsDevice.h +++ b/libs/rs/rsDevice.h @@ -37,14 +37,8 @@ public: protected: Vector<Context *> mContexts; - - }; - - - - } } #endif diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp index 6288bc4..6ae8bb8 100644 --- a/libs/rs/rsElement.cpp +++ b/libs/rs/rsElement.cpp @@ -14,26 +14,27 @@ * limitations under the License. */ -#include "rsContext.h" +#ifndef ANDROID_RS_BUILD_FOR_HOST +#include "rsContext.h" #include <GLES/gl.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#endif using namespace android; using namespace android::renderscript; -Element::Element(Context *rsc) : ObjectBase(rsc) -{ +Element::Element(Context *rsc) : ObjectBase(rsc) { mBits = 0; - mAllocFile = __FILE__; - mAllocLine = __LINE__; mFields = NULL; mFieldCount = 0; + mHasReference = false; } - -Element::~Element() -{ +Element::~Element() { for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) { if (mRSC->mStateElement.mElements[ct] == this) { mRSC->mStateElement.mElements.removeAt(ct); @@ -43,50 +44,142 @@ Element::~Element() clear(); } -void Element::clear() -{ +void Element::clear() { delete [] mFields; mFields = NULL; mFieldCount = 0; + mHasReference = false; } -size_t Element::getSizeBits() const -{ +size_t Element::getSizeBits() const { if (!mFieldCount) { return mBits; } size_t total = 0; for (size_t ct=0; ct < mFieldCount; ct++) { - total += mFields[ct].e->mBits; + total += mFields[ct].e->mBits * mFields[ct].arraySize; } return total; } -size_t Element::getFieldOffsetBits(uint32_t componentNumber) const -{ - size_t offset = 0; - for (uint32_t ct = 0; ct < componentNumber; ct++) { - offset += mFields[ct].e->mBits; +void Element::dumpLOGV(const char *prefix) const { + ObjectBase::dumpLOGV(prefix); + LOGV("%s Element: fieldCount: %i, size bytes: %i", prefix, mFieldCount, getSizeBytes()); + for (uint32_t ct = 0; ct < mFieldCount; ct++) { + LOGV("%s Element field index: %u ------------------", prefix, ct); + LOGV("%s name: %s, offsetBits: %u, arraySize: %u", + prefix, mFields[ct].name.string(), mFields[ct].offsetBits, mFields[ct].arraySize); + mFields[ct].e->dumpLOGV(prefix); } - return offset; } -void Element::dumpLOGV(const char *prefix) const -{ - ObjectBase::dumpLOGV(prefix); - LOGV("%s Element: components %i, size %i", prefix, mFieldCount, mBits); +void Element::serialize(OStream *stream) const { + // Need to identify ourselves + stream->addU32((uint32_t)getClassId()); + + String8 name(getName()); + stream->addString(&name); + + mComponent.serialize(stream); + + // Now serialize all the fields + stream->addU32(mFieldCount); for (uint32_t ct = 0; ct < mFieldCount; ct++) { - char buf[1024]; - sprintf(buf, "%s component %i: ", prefix, ct); - //mComponents[ct]->dumpLOGV(buf); + stream->addString(&mFields[ct].name); + stream->addU32(mFields[ct].arraySize); + mFields[ct].e->serialize(stream); + } +} + +Element *Element::createFromStream(Context *rsc, IStream *stream) { + // First make sure we are reading the correct object + RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); + if (classID != RS_A3D_CLASS_ID_ELEMENT) { + LOGE("element loading skipped due to invalid class id\n"); + return NULL; + } + + String8 name; + stream->loadString(&name); + + Element *elem = new Element(rsc); + elem->mComponent.loadFromStream(stream); + + elem->mFieldCount = stream->loadU32(); + if (elem->mFieldCount) { + elem->mFields = new ElementField_t [elem->mFieldCount]; + for (uint32_t ct = 0; ct < elem->mFieldCount; ct ++) { + stream->loadString(&elem->mFields[ct].name); + elem->mFields[ct].arraySize = stream->loadU32(); + Element *fieldElem = Element::createFromStream(rsc, stream); + elem->mFields[ct].e.set(fieldElem); + } + } + + // We need to check if this already exists + for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) { + Element *ee = rsc->mStateElement.mElements[ct]; + if (ee->isEqual(elem)) { + ObjectBase::checkDelete(elem); + ee->incUserRef(); + return ee; + } } + + elem->compute(); + rsc->mStateElement.mElements.push(elem); + return elem; } +bool Element::isEqual(const Element *other) const { + if (other == NULL) { + return false; + } + if (!other->getFieldCount() && !mFieldCount) { + if ((other->getType() == getType()) && + (other->getKind() == getKind()) && + (other->getComponent().getIsNormalized() == getComponent().getIsNormalized()) && + (other->getComponent().getVectorSize() == getComponent().getVectorSize())) { + return true; + } + return false; + } + if (other->getFieldCount() == mFieldCount) { + for (uint32_t i=0; i < mFieldCount; i++) { + if ((!other->mFields[i].e->isEqual(mFields[i].e.get())) || + (other->mFields[i].name.length() != mFields[i].name.length()) || + (other->mFields[i].name != mFields[i].name) || + (other->mFields[i].arraySize != mFields[i].arraySize)) { + return false; + } + } + return true; + } + return false; +} + +void Element::compute() { + if (mFieldCount == 0) { + mBits = mComponent.getBits(); + mHasReference = mComponent.isReference(); + return; + } + + size_t bits = 0; + for (size_t ct=0; ct < mFieldCount; ct++) { + mFields[ct].offsetBits = bits; + bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize; + + if (mFields[ct].e->mHasReference) { + mHasReference = true; + } + } + +} const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk, - bool isNorm, uint32_t vecSize) -{ + bool isNorm, uint32_t vecSize) { // Look for an existing match. for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) { const Element *ee = rsc->mStateElement.mElements[ct]; @@ -103,14 +196,13 @@ const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk, Element *e = new Element(rsc); e->mComponent.set(dt, dk, isNorm, vecSize); - e->mBits = e->mComponent.getBits(); + e->compute(); rsc->mStateElement.mElements.push(e); return e; } const Element * Element::create(Context *rsc, size_t count, const Element **ein, - const char **nin, const size_t * lengths) -{ + const char **nin, const size_t * lengths, const uint32_t *asin) { // Look for an existing match. for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) { const Element *ee = rsc->mStateElement.mElements[ct]; @@ -119,7 +211,8 @@ const Element * Element::create(Context *rsc, size_t count, const Element **ein, for (uint32_t i=0; i < count; i++) { if ((ee->mFields[i].e.get() != ein[i]) || (ee->mFields[i].name.length() != lengths[i]) || - (ee->mFields[i].name != nin[i])) { + (ee->mFields[i].name != nin[i]) || + (ee->mFields[i].arraySize != asin[i])) { match = false; break; } @@ -137,35 +230,15 @@ const Element * Element::create(Context *rsc, size_t count, const Element **ein, for (size_t ct=0; ct < count; ct++) { e->mFields[ct].e.set(ein[ct]); e->mFields[ct].name.setTo(nin[ct], lengths[ct]); + e->mFields[ct].arraySize = asin[ct]; } + e->compute(); rsc->mStateElement.mElements.push(e); return e; } -String8 Element::getCStructBody(uint32_t indent) const -{ - String8 si; - for (uint32_t ct=0; ct < indent; ct++) { - si.append(" "); - } - - String8 s(si); - s.append("{\n"); - for (uint32_t ct = 0; ct < mFieldCount; ct++) { - s.append(si); - s.append(mFields[ct].e->getCType(indent+4)); - s.append(" "); - s.append(mFields[ct].name); - s.append(";\n"); - } - s.append(si); - s.append("}"); - return s; -} - -String8 Element::getCType(uint32_t indent) const -{ +String8 Element::getGLSLType(uint32_t indent) const { String8 s; for (uint32_t ct=0; ct < indent; ct++) { s.append(" "); @@ -173,45 +246,96 @@ String8 Element::getCType(uint32_t indent) const if (!mFieldCount) { // Basic component. - s.append(mComponent.getCType()); + s.append(mComponent.getGLSLType()); } else { - s.append("struct "); - s.append(getCStructBody(indent)); + rsAssert(0); + //s.append("struct "); + //s.append(getCStructBody(indent)); } return s; } -String8 Element::getGLSLType(uint32_t indent) const -{ - String8 s; - for (uint32_t ct=0; ct < indent; ct++) { - s.append(" "); +void Element::incRefs(const void *ptr) const { + if (!mFieldCount) { + if (mComponent.isReference()) { + ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr); + ObjectBase *ob = obp[0]; + if (ob) ob->incSysRef(); + } + return; } + const uint8_t *p = static_cast<const uint8_t *>(ptr); + for (uint32_t i=0; i < mFieldCount; i++) { + if (mFields[i].e->mHasReference) { + p = &p[mFields[i].offsetBits >> 3]; + for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) { + mFields[i].e->incRefs(p); + p += mFields[i].e->getSizeBytes(); + } + } + } +} + +void Element::decRefs(const void *ptr) const { if (!mFieldCount) { - // Basic component. - s.append(mComponent.getGLSLType()); - } else { - rsAssert(0); - //s.append("struct "); - //s.append(getCStructBody(indent)); + if (mComponent.isReference()) { + ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr); + ObjectBase *ob = obp[0]; + if (ob) ob->decSysRef(); + } + return; } - return s; + const uint8_t *p = static_cast<const uint8_t *>(ptr); + for (uint32_t i=0; i < mFieldCount; i++) { + if (mFields[i].e->mHasReference) { + p = &p[mFields[i].offsetBits >> 3]; + for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) { + mFields[i].e->decRefs(p); + p += mFields[i].e->getSizeBytes(); + } + } + } } - -ElementState::ElementState() -{ +ElementState::ElementState() { + const uint32_t initialCapacity = 32; + mBuilderElements.setCapacity(initialCapacity); + mBuilderNameStrings.setCapacity(initialCapacity); + mBuilderNameLengths.setCapacity(initialCapacity); + mBuilderArrays.setCapacity(initialCapacity); } -ElementState::~ElementState() -{ +ElementState::~ElementState() { rsAssert(!mElements.size()); } +void ElementState::elementBuilderBegin() { + mBuilderElements.clear(); + mBuilderNameStrings.clear(); + mBuilderNameLengths.clear(); + mBuilderArrays.clear(); +} + +void ElementState::elementBuilderAdd(const Element *e, const char *nameStr, uint32_t arraySize) { + mBuilderElements.push(e); + mBuilderNameStrings.push(nameStr); + mBuilderNameLengths.push(strlen(nameStr)); + mBuilderArrays.push(arraySize); + +} + +const Element *ElementState::elementBuilderCreate(Context *rsc) { + return Element::create(rsc, mBuilderElements.size(), + &(mBuilderElements.editArray()[0]), + &(mBuilderNameStrings.editArray()[0]), + mBuilderNameLengths.editArray(), + mBuilderArrays.editArray()); +} + ///////////////////////////////////////// // @@ -223,9 +347,7 @@ RsElement rsi_ElementCreate(Context *rsc, RsDataType dt, RsDataKind dk, bool norm, - uint32_t vecSize) -{ - //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize); + uint32_t vecSize) { const Element *e = Element::create(rsc, dt, dk, norm, vecSize); e->incUserRef(); return (RsElement)e; @@ -235,14 +357,35 @@ RsElement rsi_ElementCreate2(Context *rsc, size_t count, const RsElement * ein, const char ** names, - const size_t * nameLengths) -{ - //LOGE("rsi_ElementCreate2 %i", count); - const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths); + const size_t * nameLengths, + const uint32_t * arraySizes) { + const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths, arraySizes); e->incUserRef(); return (RsElement)e; } +} +} + +void rsaElementGetNativeData(RsContext con, RsElement elem, uint32_t *elemData, uint32_t elemDataSize) { + rsAssert(elemDataSize == 5); + // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements + Element *e = static_cast<Element *>(elem); + (*elemData++) = (uint32_t)e->getType(); + (*elemData++) = (uint32_t)e->getKind(); + (*elemData++) = e->getComponent().getIsNormalized() ? 1 : 0; + (*elemData++) = e->getComponent().getVectorSize(); + (*elemData++) = e->getFieldCount(); } + +void rsaElementGetSubElements(RsContext con, RsElement elem, uint32_t *ids, const char **names, uint32_t dataSize) { + Element *e = static_cast<Element *>(elem); + rsAssert(e->getFieldCount() == dataSize); + + for (uint32_t i = 0; i < dataSize; i ++) { + e->getField(i)->incUserRef(); + ids[i] = (uint32_t)e->getField(i); + names[i] = e->getFieldName(i); + } } diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h index 02a1ca2..26e2760 100644 --- a/libs/rs/rsElement.h +++ b/libs/rs/rsElement.h @@ -25,10 +25,8 @@ namespace android { namespace renderscript { - // An element is a group of Components that occupies one cell in a structure. -class Element : public ObjectBase -{ +class Element : public ObjectBase { public: ~Element(); @@ -40,30 +38,40 @@ public: return (getSizeBits() + 7) >> 3; } - size_t getFieldOffsetBits(uint32_t componentNumber) const; + size_t getFieldOffsetBits(uint32_t componentNumber) const { + return mFields[componentNumber].offsetBits; + } size_t getFieldOffsetBytes(uint32_t componentNumber) const { - return (getFieldOffsetBits(componentNumber) + 7) >> 3; + return mFields[componentNumber].offsetBits >> 3; } uint32_t getFieldCount() const {return mFieldCount;} const Element * getField(uint32_t idx) const {return mFields[idx].e.get();} const char * getFieldName(uint32_t idx) const {return mFields[idx].name.string();} + uint32_t getFieldArraySize(uint32_t idx) const {return mFields[idx].arraySize;} const Component & getComponent() const {return mComponent;} RsDataType getType() const {return mComponent.getType();} RsDataKind getKind() const {return mComponent.getKind();} uint32_t getBits() const {return mBits;} - String8 getCType(uint32_t indent=0) const; - String8 getCStructBody(uint32_t indent=0) const; String8 getGLSLType(uint32_t indent=0) const; void dumpLOGV(const char *prefix) const; + virtual void serialize(OStream *stream) const; + virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ELEMENT; } + static Element *createFromStream(Context *rsc, IStream *stream); static const Element * create(Context *rsc, RsDataType dt, RsDataKind dk, bool isNorm, uint32_t vecSize); static const Element * create(Context *rsc, size_t count, const Element **, - const char **, const size_t * lengths); + const char **, const size_t * lengths, const uint32_t *asin); + + void incRefs(const void *) const; + void decRefs(const void *) const; + bool getHasReferences() const {return mHasReference;} + + bool isEqual(const Element *other) const; protected: // deallocate any components that are part of this element. @@ -72,15 +80,20 @@ protected: typedef struct { String8 name; ObjectBaseRef<const Element> e; + uint32_t offsetBits; + uint32_t arraySize; } ElementField_t; ElementField_t *mFields; size_t mFieldCount; + bool mHasReference; Element(Context *); Component mComponent; uint32_t mBits; + + void compute(); }; @@ -89,8 +102,17 @@ public: ElementState(); ~ElementState(); + void elementBuilderBegin(); + void elementBuilderAdd(const Element *e, const char *nameStr, uint32_t arraySize); + const Element *elementBuilderCreate(Context *rsc); + // Cache of all existing elements. - Vector<const Element *> mElements; + Vector<Element *> mElements; +private: + Vector<const Element *> mBuilderElements; + Vector<const char*> mBuilderNameStrings; + Vector<size_t> mBuilderNameLengths; + Vector<uint32_t> mBuilderArrays; }; diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp index e3272c5..d34ddd6 100644 --- a/libs/rs/rsFileA3D.cpp +++ b/libs/rs/rsFileA3D.cpp @@ -15,81 +15,181 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif - -#include <utils/String8.h> #include "rsFileA3D.h" #include "rsMesh.h" +#include "rsAnimation.h" + using namespace android; using namespace android::renderscript; +FileA3D::FileA3D(Context *rsc) : ObjectBase(rsc) { + mAlloc = NULL; + mData = NULL; + mWriteStream = NULL; + mReadStream = NULL; + mAsset = NULL; + mMajorVersion = 0; + mMinorVersion = 1; + mDataSize = 0; +} -FileA3D::FileA3D() -{ - mRsc = NULL; +FileA3D::~FileA3D() { + for (size_t i = 0; i < mIndex.size(); i ++) { + delete mIndex[i]; + } + for (size_t i = 0; i < mWriteIndex.size(); i ++) { + delete mWriteIndex[i]; + } + if (mWriteStream) { + delete mWriteStream; + } + if (mReadStream) { + delete mWriteStream; + } + if (mAlloc) { + free(mAlloc); + } + if (mAsset) { + delete mAsset; + } } -FileA3D::~FileA3D() -{ +void FileA3D::parseHeader(IStream *headerStream) { + mMajorVersion = headerStream->loadU32(); + mMinorVersion = headerStream->loadU32(); + uint32_t flags = headerStream->loadU32(); + mUse64BitOffsets = (flags & 1) != 0; + + uint32_t numIndexEntries = headerStream->loadU32(); + for (uint32_t i = 0; i < numIndexEntries; i ++) { + A3DIndexEntry *entry = new A3DIndexEntry(); + headerStream->loadString(&entry->mObjectName); + LOGV("Header data, entry name = %s", entry->mObjectName.string()); + entry->mType = (RsA3DClassID)headerStream->loadU32(); + if (mUse64BitOffsets){ + entry->mOffset = headerStream->loadOffset(); + entry->mLength = headerStream->loadOffset(); + } else { + entry->mOffset = headerStream->loadU32(); + entry->mLength = headerStream->loadU32(); + } + entry->mRsObj = NULL; + mIndex.push(entry); + } +} + +bool FileA3D::load(Asset *asset) { + mAsset = asset; + return load(asset->getBuffer(false), asset->getLength()); +} + +bool FileA3D::load(const void *data, size_t length) { + const uint8_t *localData = (const uint8_t *)data; + + size_t lengthRemaining = length; + size_t magicStrLen = 12; + if ((length < magicStrLen) || + memcmp(data, "Android3D_ff", magicStrLen)) { + return false; + } + + localData += magicStrLen; + lengthRemaining -= magicStrLen; + + // Next we get our header size + uint64_t headerSize = 0; + if (lengthRemaining < sizeof(headerSize)) { + return false; + } + + memcpy(&headerSize, localData, sizeof(headerSize)); + localData += sizeof(headerSize); + lengthRemaining -= sizeof(headerSize); + + if (lengthRemaining < headerSize) { + return false; + } + + // Now open the stream to parse the header + IStream headerStream(localData, false); + parseHeader(&headerStream); + + localData += headerSize; + lengthRemaining -= headerSize; + + if (lengthRemaining < sizeof(mDataSize)) { + return false; + } + + // Read the size of the data + memcpy(&mDataSize, localData, sizeof(mDataSize)); + localData += sizeof(mDataSize); + lengthRemaining -= sizeof(mDataSize); + + if (lengthRemaining < mDataSize) { + return false; + } + + // We should know enough to read the file in at this point. + mData = (uint8_t *)localData; + mReadStream = new IStream(mData, mUse64BitOffsets); + + return true; } -bool FileA3D::load(Context *rsc, FILE *f) -{ +bool FileA3D::load(FILE *f) { char magicString[12]; size_t len; - LOGE("file open 1"); + LOGV("file open 1"); len = fread(magicString, 1, 12, f); if ((len != 12) || memcmp(magicString, "Android3D_ff", 12)) { return false; } - LOGE("file open 2"); - len = fread(&mMajorVersion, 1, sizeof(mMajorVersion), f); - if (len != sizeof(mMajorVersion)) { + // Next thing is the size of the header + uint64_t headerSize = 0; + len = fread(&headerSize, 1, sizeof(headerSize), f); + if (len != sizeof(headerSize) || headerSize == 0) { return false; } - LOGE("file open 3"); - len = fread(&mMinorVersion, 1, sizeof(mMinorVersion), f); - if (len != sizeof(mMinorVersion)) { + uint8_t *headerData = (uint8_t *)malloc(headerSize); + if (!headerData) { return false; } - LOGE("file open 4"); - uint32_t flags; - len = fread(&flags, 1, sizeof(flags), f); - if (len != sizeof(flags)) { + len = fread(headerData, 1, headerSize, f); + if (len != headerSize) { return false; } - mUse64BitOffsets = (flags & 1) != 0; - LOGE("file open 64bit = %i", mUse64BitOffsets); + // Now open the stream to parse the header + IStream headerStream(headerData, false); + parseHeader(&headerStream); - if (mUse64BitOffsets) { - len = fread(&mDataSize, 1, sizeof(mDataSize), f); - if (len != sizeof(mDataSize)) { - return false; - } - } else { - uint32_t tmp; - len = fread(&tmp, 1, sizeof(tmp), f); - if (len != sizeof(tmp)) { - return false; - } - mDataSize = tmp; + free(headerData); + + // Next thing is the size of the header + len = fread(&mDataSize, 1, sizeof(mDataSize), f); + if (len != sizeof(mDataSize) || mDataSize == 0) { + return false; } - LOGE("file open size = %lli", mDataSize); + LOGV("file open size = %lli", mDataSize); // We should know enough to read the file in at this point. - fseek(f, SEEK_SET, 0); - mAlloc= malloc(mDataSize); + mAlloc = malloc(mDataSize); if (!mAlloc) { return false; } @@ -99,288 +199,260 @@ bool FileA3D::load(Context *rsc, FILE *f) return false; } - LOGE("file start processing"); - return process(rsc); + mReadStream = new IStream(mData, mUse64BitOffsets); + + LOGV("Header is read an stream initialized"); + return true; } -bool FileA3D::processIndex(Context *rsc, A3DIndexEntry *ie) -{ - bool ret = false; - IO io(mData + ie->mOffset, mUse64BitOffsets); - - LOGE("process index, type %i", ie->mType); - - switch(ie->mType) { - case CHUNK_ELEMENT: - processChunk_Element(rsc, &io, ie); - break; - case CHUNK_ELEMENT_SOURCE: - processChunk_ElementSource(rsc, &io, ie); - break; - case CHUNK_VERTICIES: - processChunk_Verticies(rsc, &io, ie); - break; - case CHUNK_MESH: - processChunk_Mesh(rsc, &io, ie); - break; - case CHUNK_PRIMITIVE: - processChunk_Primitive(rsc, &io, ie); - break; - default: - LOGE("FileA3D Unknown chunk type"); - break; - } - return (ie->mRsObj != NULL); +size_t FileA3D::getNumIndexEntries() const { + return mIndex.size(); } -bool FileA3D::process(Context *rsc) -{ - LOGE("process"); - IO io(mData + 12, mUse64BitOffsets); - bool ret = true; - - // Build the index first - LOGE("process 1"); - io.loadU32(); // major version, already loaded - io.loadU32(); // minor version, already loaded - LOGE("process 2"); - - io.loadU32(); // flags - io.loadOffset(); // filesize, already loaded. - LOGE("process 4"); - uint64_t mIndexOffset = io.loadOffset(); - uint64_t mStringOffset = io.loadOffset(); - - LOGE("process mIndexOffset= 0x%016llx", mIndexOffset); - LOGE("process mStringOffset= 0x%016llx", mStringOffset); - - IO index(mData + mIndexOffset, mUse64BitOffsets); - IO stringTable(mData + mStringOffset, mUse64BitOffsets); - - uint32_t stringEntryCount = stringTable.loadU32(); - LOGE("stringEntryCount %i", stringEntryCount); - mStrings.setCapacity(stringEntryCount); - mStringIndexValues.setCapacity(stringEntryCount); - if (stringEntryCount) { - uint32_t stringType = stringTable.loadU32(); - LOGE("stringType %i", stringType); - rsAssert(stringType==0); - for (uint32_t ct = 0; ct < stringEntryCount; ct++) { - uint64_t offset = stringTable.loadOffset(); - LOGE("string offset 0x%016llx", offset); - IO tmp(mData + offset, mUse64BitOffsets); - String8 s; - tmp.loadString(&s); - LOGE("string %s", s.string()); - mStrings.push(s); - } +const FileA3D::A3DIndexEntry *FileA3D::getIndexEntry(size_t index) const { + if (index < mIndex.size()) { + return mIndex[index]; } + return NULL; +} - LOGE("strings done"); - uint32_t indexEntryCount = index.loadU32(); - LOGE("index count %i", indexEntryCount); - mIndex.setCapacity(indexEntryCount); - for (uint32_t ct = 0; ct < indexEntryCount; ct++) { - A3DIndexEntry e; - uint32_t stringIndex = index.loadU32(); - LOGE("index %i", ct); - LOGE(" string index %i", stringIndex); - e.mType = (A3DChunkType)index.loadU32(); - LOGE(" type %i", e.mType); - e.mOffset = index.loadOffset(); - LOGE(" offset 0x%016llx", e.mOffset); - - if (stringIndex && (stringIndex < mStrings.size())) { - e.mID = mStrings[stringIndex]; - mStringIndexValues.editItemAt(stringIndex) = ct; - LOGE(" id %s", e.mID.string()); - } +ObjectBase *FileA3D::initializeFromEntry(size_t index) { + if (index >= mIndex.size()) { + return NULL; + } - mIndex.push(e); + FileA3D::A3DIndexEntry *entry = mIndex[index]; + if (!entry) { + return NULL; } - LOGE("index done"); - // At this point the index should be fully populated. - // We can now walk though it and load all the objects. - for (uint32_t ct = 0; ct < indexEntryCount; ct++) { - LOGE("processing index entry %i", ct); - processIndex(rsc, &mIndex.editItemAt(ct)); + if (entry->mRsObj) { + entry->mRsObj->incUserRef(); + return entry->mRsObj; } - return ret; + // Seek to the beginning of object + mReadStream->reset(entry->mOffset); + switch (entry->mType) { + case RS_A3D_CLASS_ID_UNKNOWN: + return NULL; + case RS_A3D_CLASS_ID_MESH: + entry->mRsObj = Mesh::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_TYPE: + entry->mRsObj = Type::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_ELEMENT: + entry->mRsObj = Element::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_ALLOCATION: + entry->mRsObj = Allocation::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_PROGRAM_VERTEX: + entry->mRsObj = ProgramVertex::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_PROGRAM_RASTER: + entry->mRsObj = ProgramRaster::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_PROGRAM_FRAGMENT: + entry->mRsObj = ProgramFragment::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_PROGRAM_STORE: + entry->mRsObj = ProgramStore::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_SAMPLER: + entry->mRsObj = Sampler::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_ANIMATION: + entry->mRsObj = Animation::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_ADAPTER_1D: + entry->mRsObj = Adapter1D::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_ADAPTER_2D: + entry->mRsObj = Adapter2D::createFromStream(mRSC, mReadStream); + break; + case RS_A3D_CLASS_ID_SCRIPT_C: + return NULL; + } + if (entry->mRsObj) { + entry->mRsObj->incUserRef(); + } + return entry->mRsObj; } +bool FileA3D::writeFile(const char *filename) { + if (!mWriteStream) { + LOGE("No objects to write\n"); + return false; + } + if (mWriteStream->getPos() == 0) { + LOGE("No objects to write\n"); + return false; + } -FileA3D::IO::IO(const uint8_t *buf, bool use64) -{ - mData = buf; - mPos = 0; - mUse64 = use64; -} + FILE *writeHandle = fopen(filename, "wb"); + if (!writeHandle) { + LOGE("Couldn't open the file for writing\n"); + return false; + } -uint64_t FileA3D::IO::loadOffset() -{ - uint64_t tmp; - if (mUse64) { - mPos = (mPos + 7) & (~7); - tmp = reinterpret_cast<const uint64_t *>(&mData[mPos])[0]; - mPos += sizeof(uint64_t); - return tmp; + // Open a new stream to make writing the header easier + OStream headerStream(5*1024, false); + headerStream.addU32(mMajorVersion); + headerStream.addU32(mMinorVersion); + uint32_t is64Bit = 0; + headerStream.addU32(is64Bit); + + uint32_t writeIndexSize = mWriteIndex.size(); + headerStream.addU32(writeIndexSize); + for (uint32_t i = 0; i < writeIndexSize; i ++) { + headerStream.addString(&mWriteIndex[i]->mObjectName); + headerStream.addU32((uint32_t)mWriteIndex[i]->mType); + if (mUse64BitOffsets){ + headerStream.addOffset(mWriteIndex[i]->mOffset); + headerStream.addOffset(mWriteIndex[i]->mLength); + } else { + uint32_t offset = (uint32_t)mWriteIndex[i]->mOffset; + headerStream.addU32(offset); + offset = (uint32_t)mWriteIndex[i]->mLength; + headerStream.addU32(offset); + } } - return loadU32(); -} -void FileA3D::IO::loadString(String8 *s) -{ - LOGE("loadString"); - uint32_t len = loadU32(); - LOGE("loadString len %i", len); - s->setTo((const char *)&mData[mPos], len); - mPos += len; -} + // Write our magic string so we know we are reading the right file + String8 magicString(A3D_MAGIC_KEY); + fwrite(magicString.string(), sizeof(char), magicString.size(), writeHandle); + + // Store the size of the header to make it easier to parse when we read it + uint64_t headerSize = headerStream.getPos(); + fwrite(&headerSize, sizeof(headerSize), 1, writeHandle); + + // Now write our header + fwrite(headerStream.getPtr(), sizeof(uint8_t), headerStream.getPos(), writeHandle); + // Now write the size of the data part of the file for easier parsing later + uint64_t fileDataSize = mWriteStream->getPos(); + fwrite(&fileDataSize, sizeof(fileDataSize), 1, writeHandle); -void FileA3D::processChunk_Mesh(Context *rsc, IO *io, A3DIndexEntry *ie) -{ - Mesh * m = new Mesh(rsc); + fwrite(mWriteStream->getPtr(), sizeof(uint8_t), mWriteStream->getPos(), writeHandle); - m->mPrimitivesCount = io->loadU32(); - m->mPrimitives = new Mesh::Primitive_t *[m->mPrimitivesCount]; + int status = fclose(writeHandle); + + if (status != 0) { + LOGE("Couldn't close file\n"); + return false; + } - for (uint32_t ct = 0; ct < m->mPrimitivesCount; ct++) { - uint32_t index = io->loadU32(); + return true; +} - m->mPrimitives[ct] = (Mesh::Primitive_t *)mIndex[index].mRsObj; +void FileA3D::appendToFile(ObjectBase *obj) { + if (!obj) { + return; + } + if (!mWriteStream) { + const uint64_t initialStreamSize = 256*1024; + mWriteStream = new OStream(initialStreamSize, false); } - ie->mRsObj = m; + A3DIndexEntry *indexEntry = new A3DIndexEntry(); + indexEntry->mObjectName.setTo(obj->getName()); + indexEntry->mType = obj->getClassId(); + indexEntry->mOffset = mWriteStream->getPos(); + indexEntry->mRsObj = obj; + mWriteIndex.push(indexEntry); + obj->serialize(mWriteStream); + indexEntry->mLength = mWriteStream->getPos() - indexEntry->mOffset; + mWriteStream->align(4); } -void FileA3D::processChunk_Primitive(Context *rsc, IO *io, A3DIndexEntry *ie) -{ - Mesh::Primitive_t * p = new Mesh::Primitive_t; +RsObjectBase rsaFileA3DGetEntryByIndex(RsContext con, uint32_t index, RsFile file) { + FileA3D *fa3d = static_cast<FileA3D *>(file); + if (!fa3d) { + LOGE("Can't load entry. No valid file"); + return NULL; + } - p->mIndexCount = io->loadU32(); - uint32_t vertIdx = io->loadU32(); - p->mRestartCounts = io->loadU16(); - uint32_t bits = io->loadU8(); - p->mType = (RsPrimitive)io->loadU8(); + ObjectBase *obj = fa3d->initializeFromEntry(index); + LOGV("Returning object with name %s", obj->getName()); - LOGE("processChunk_Primitive count %i, bits %i", p->mIndexCount, bits); + return obj; +} - p->mVerticies = (Mesh::Verticies_t *)mIndex[vertIdx].mRsObj; - p->mIndicies = new uint16_t[p->mIndexCount]; - for (uint32_t ct = 0; ct < p->mIndexCount; ct++) { - switch(bits) { - case 8: - p->mIndicies[ct] = io->loadU8(); - break; - case 16: - p->mIndicies[ct] = io->loadU16(); - break; - case 32: - p->mIndicies[ct] = io->loadU32(); - break; - } - LOGE(" idx %i", p->mIndicies[ct]); - } - - if (p->mRestartCounts) { - p->mRestarts = new uint16_t[p->mRestartCounts]; - for (uint32_t ct = 0; ct < p->mRestartCounts; ct++) { - switch(bits) { - case 8: - p->mRestarts[ct] = io->loadU8(); - break; - case 16: - p->mRestarts[ct] = io->loadU16(); - break; - case 32: - p->mRestarts[ct] = io->loadU32(); - break; - } - LOGE(" idx %i", p->mRestarts[ct]); - } +void rsaFileA3DGetNumIndexEntries(RsContext con, int32_t *numEntries, RsFile file) { + FileA3D *fa3d = static_cast<FileA3D *>(file); + + if (fa3d) { + *numEntries = fa3d->getNumIndexEntries(); } else { - p->mRestarts = NULL; + *numEntries = 0; } - - ie->mRsObj = p; } -void FileA3D::processChunk_Verticies(Context *rsc, IO *io, A3DIndexEntry *ie) -{ - Mesh::Verticies_t *cv = new Mesh::Verticies_t; - cv->mAllocationCount = io->loadU32(); - cv->mAllocations = new Allocation *[cv->mAllocationCount]; - LOGE("processChunk_Verticies count %i", cv->mAllocationCount); - for (uint32_t ct = 0; ct < cv->mAllocationCount; ct++) { - uint32_t i = io->loadU32(); - cv->mAllocations[ct] = (Allocation *)mIndex[i].mRsObj; - LOGE(" idx %i", i); - } - ie->mRsObj = cv; -} +void rsaFileA3DGetIndexEntries(RsContext con, RsFileIndexEntry *fileEntries, uint32_t numEntries, RsFile file) { + FileA3D *fa3d = static_cast<FileA3D *>(file); -void FileA3D::processChunk_Element(Context *rsc, IO *io, A3DIndexEntry *ie) -{ - /* - rsi_ElementBegin(rsc); - - uint32_t count = io->loadU32(); - LOGE("processChunk_Element count %i", count); - while (count--) { - RsDataKind dk = (RsDataKind)io->loadU8(); - RsDataType dt = (RsDataType)io->loadU8(); - uint32_t bits = io->loadU8(); - bool isNorm = io->loadU8() != 0; - LOGE(" %i %i %i %i", dk, dt, bits, isNorm); - rsi_ElementAdd(rsc, dk, dt, isNorm, bits, 0); - } - LOGE("processChunk_Element create"); - ie->mRsObj = rsi_ElementCreate(rsc); - */ -} + if (!fa3d) { + LOGE("Can't load index entries. No valid file"); + return; + } -void FileA3D::processChunk_ElementSource(Context *rsc, IO *io, A3DIndexEntry *ie) -{ - uint32_t index = io->loadU32(); - uint32_t count = io->loadU32(); + uint32_t numFileEntries = fa3d->getNumIndexEntries(); + if (numFileEntries != numEntries || numEntries == 0 || fileEntries == NULL) { + LOGE("Can't load index entries. Invalid number requested"); + return; + } - LOGE("processChunk_ElementSource count %i, index %i", count, index); + for (uint32_t i = 0; i < numFileEntries; i ++) { + const FileA3D::A3DIndexEntry *entry = fa3d->getIndexEntry(i); + fileEntries[i].classID = entry->getType(); + fileEntries[i].objectName = entry->getObjectName().string(); + } +} - RsElement e = (RsElement)mIndex[index].mRsObj; +RsFile rsaFileA3DCreateFromMemory(RsContext con, const void *data, uint32_t len) { + if (data == NULL) { + LOGE("File load failed. Asset stream is NULL"); + return NULL; + } - RsAllocation a = rsi_AllocationCreateSized(rsc, e, count); - Allocation * alloc = static_cast<Allocation *>(a); + Context *rsc = static_cast<Context *>(con); + FileA3D *fa3d = new FileA3D(rsc); + fa3d->incUserRef(); - float * data = (float *)alloc->getPtr(); - while(count--) { - *data = io->loadF(); - LOGE(" %f", *data); - data++; - } - ie->mRsObj = alloc; + fa3d->load(data, len); + return fa3d; } -namespace android { -namespace renderscript { +RsFile rsaFileA3DCreateFromAsset(RsContext con, void *_asset) { + Context *rsc = static_cast<Context *>(con); + Asset *asset = static_cast<Asset *>(_asset); + FileA3D *fa3d = new FileA3D(rsc); + fa3d->incUserRef(); + fa3d->load(asset); + return fa3d; +} -RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len) -{ - FileA3D *fa3d = new FileA3D; +RsFile rsaFileA3DCreateFromFile(RsContext con, const char *path) { + if (path == NULL) { + LOGE("File load failed. Path is NULL"); + return NULL; + } - FILE *f = fopen("/sdcard/test.a3d", "rb"); + Context *rsc = static_cast<Context *>(con); + FileA3D *fa3d = NULL; + + FILE *f = fopen(path, "rb"); if (f) { - fa3d->load(rsc, f); + fa3d = new FileA3D(rsc); + fa3d->incUserRef(); + fa3d->load(f); fclose(f); - return fa3d; + } else { + LOGE("Could not open file %s", path); } - delete fa3d; - return NULL; -} - -} + return fa3d; } diff --git a/libs/rs/rsFileA3D.h b/libs/rs/rsFileA3D.h index 9ee08ec..056b5af 100644 --- a/libs/rs/rsFileA3D.h +++ b/libs/rs/rsFileA3D.h @@ -18,20 +18,23 @@ #define ANDROID_RS_FILE_A3D_H #include "RenderScript.h" -#include "rsFileA3DDecls.h" #include "rsMesh.h" #include <utils/String8.h> +#include <utils/Asset.h> +#include "rsStream.h" #include <stdio.h> +#define A3D_MAGIC_KEY "Android3D_ff" + // --------------------------------------------------------------------------- namespace android { + namespace renderscript { -class FileA3D -{ +class FileA3D : public ObjectBase { public: - FileA3D(); + FileA3D(Context *rsc); ~FileA3D(); uint32_t mMajorVersion; @@ -40,78 +43,55 @@ public: uint64_t mStringTableOffset; bool mUse64BitOffsets; - struct A3DIndexEntry { - String8 mID; - A3DChunkType mType; + class A3DIndexEntry { + String8 mObjectName; + RsA3DClassID mType; uint64_t mOffset; - void * mRsObj; - }; - - bool load(Context *rsc, FILE *f); - -protected: - class IO - { + uint64_t mLength; + ObjectBase *mRsObj; public: - IO(const uint8_t *, bool use64); - - float loadF() { - mPos = (mPos + 3) & (~3); - float tmp = reinterpret_cast<const float *>(&mData[mPos])[0]; - mPos += sizeof(float); - return tmp; - } - int32_t loadI32() { - mPos = (mPos + 3) & (~3); - int32_t tmp = reinterpret_cast<const int32_t *>(&mData[mPos])[0]; - mPos += sizeof(int32_t); - return tmp; + friend class FileA3D; + const String8 &getObjectName() const { + return mObjectName; } - uint32_t loadU32() { - mPos = (mPos + 3) & (~3); - uint32_t tmp = reinterpret_cast<const uint32_t *>(&mData[mPos])[0]; - mPos += sizeof(uint32_t); - return tmp; + RsA3DClassID getType() const { + return mType; } - uint16_t loadU16() { - mPos = (mPos + 1) & (~1); - uint16_t tmp = reinterpret_cast<const uint16_t *>(&mData[mPos])[0]; - mPos += sizeof(uint16_t); - return tmp; - } - uint8_t loadU8() { - uint8_t tmp = reinterpret_cast<const uint8_t *>(&mData[mPos])[0]; - mPos += sizeof(uint8_t); - return tmp; - } - uint64_t loadOffset(); - void loadString(String8 *s); - uint64_t getPos() const {return mPos;} - const uint8_t * getPtr() const; - protected: - const uint8_t * mData; - uint64_t mPos; - bool mUse64; }; + bool load(FILE *f); + bool load(Asset *asset); + bool load(const void *data, size_t length); + + size_t getNumIndexEntries() const; + const A3DIndexEntry* getIndexEntry(size_t index) const; + ObjectBase *initializeFromEntry(size_t index); + + void appendToFile(ObjectBase *obj); + bool writeFile(const char *filename); + + // Currently files do not get serialized, + // but we need to inherit from ObjectBase for ref tracking + virtual void serialize(OStream *stream) const { + } + virtual RsA3DClassID getClassId() const { + return RS_A3D_CLASS_ID_UNKNOWN; + } + +protected: - bool process(Context *rsc); - bool processIndex(Context *rsc, A3DIndexEntry *); - void processChunk_Mesh(Context *rsc, IO *io, A3DIndexEntry *ie); - void processChunk_Primitive(Context *rsc, IO *io, A3DIndexEntry *ie); - void processChunk_Verticies(Context *rsc, IO *io, A3DIndexEntry *ie); - void processChunk_Element(Context *rsc, IO *io, A3DIndexEntry *ie); - void processChunk_ElementSource(Context *rsc, IO *io, A3DIndexEntry *ie); + void parseHeader(IStream *headerStream); const uint8_t * mData; void * mAlloc; uint64_t mDataSize; - Context * mRsc; + Asset *mAsset; - Vector<A3DIndexEntry> mIndex; - Vector<String8> mStrings; - Vector<uint32_t> mStringIndexValues; + OStream *mWriteStream; + Vector<A3DIndexEntry*> mWriteIndex; + IStream *mReadStream; + Vector<A3DIndexEntry*> mIndex; }; diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp new file mode 100644 index 0000000..8571c32 --- /dev/null +++ b/libs/rs/rsFont.cpp @@ -0,0 +1,833 @@ + +/* + * 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. + */ + +#ifndef ANDROID_RS_BUILD_FOR_HOST +#include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif + +#include "rsFont.h" +#include "rsProgramFragment.h" +#include <cutils/properties.h> +#include FT_BITMAP_H + +#include <GLES/gl.h> +#include <GLES/glext.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +using namespace android; +using namespace android::renderscript; + +Font::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { + mInitialized = false; + mHasKerning = false; + mFace = NULL; +} + +bool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { + if (mInitialized) { + LOGE("Reinitialization of fonts not supported"); + return false; + } + + FT_Error error = 0; + if (data != NULL && dataLen > 0) { + error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace); + } else { + error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); + } + + if (error) { + LOGE("Unable to initialize font %s", name); + return false; + } + + mFontName = name; + mFontSize = fontSize; + mDpi = dpi; + + error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); + if (error) { + LOGE("Unable to set font size on %s", name); + return false; + } + + mHasKerning = FT_HAS_KERNING(mFace); + + mInitialized = true; + return true; +} + +void Font::invalidateTextureCache() { + for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { + mCachedGlyphs.valueAt(i)->mIsValid = false; + } +} + +void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { + FontState *state = &mRSC->mStateFont; + + int32_t nPenX = x + glyph->mBitmapLeft; + int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; + + float u1 = glyph->mBitmapMinU; + float u2 = glyph->mBitmapMaxU; + float v1 = glyph->mBitmapMinV; + float v2 = glyph->mBitmapMaxV; + + int32_t width = (int32_t) glyph->mBitmapWidth; + int32_t height = (int32_t) glyph->mBitmapHeight; + + state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, + nPenX + width, nPenY, 0, u2, v2, + nPenX + width, nPenY - height, 0, u2, v1, + nPenX, nPenY - height, 0, u1, v1); +} + +void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, + uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { + int32_t nPenX = x + glyph->mBitmapLeft; + int32_t nPenY = y + glyph->mBitmapTop; + + uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; + uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; + + FontState *state = &mRSC->mStateFont; + uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); + const uint8_t* cacheBuffer = state->getTextTextureData(); + + uint32_t cacheX = 0, cacheY = 0; + int32_t bX = 0, bY = 0; + for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { + for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { + if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { + LOGE("Skipping invalid index"); + continue; + } + uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; + bitmap[bY * bitmapW + bX] = tempCol; + } + } +} + +void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { + int32_t nPenX = x + glyph->mBitmapLeft; + int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; + + int32_t width = (int32_t) glyph->mBitmapWidth; + int32_t height = (int32_t) glyph->mBitmapHeight; + + // 0, 0 is top left, so bottom is a positive number + if (bounds->bottom < nPenY) { + bounds->bottom = nPenY; + } + if (bounds->left > nPenX) { + bounds->left = nPenX; + } + if (bounds->right < nPenX + width) { + bounds->right = nPenX + width; + } + if (bounds->top > nPenY - height) { + bounds->top = nPenY - height; + } +} + +void Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, + uint32_t start, int32_t numGlyphs, + RenderMode mode, Rect *bounds, + uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { + if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { + return; + } + + if (mode == Font::MEASURE) { + if (bounds == NULL) { + LOGE("No return rectangle provided to measure text"); + return; + } + // Reset min and max of the bounding box to something large + bounds->set(1e6, -1e6, 1e6, -1e6); + } + + int32_t penX = x, penY = y; + int32_t glyphsLeft = 1; + if (numGlyphs > 0) { + glyphsLeft = numGlyphs; + } + + size_t index = start; + size_t nextIndex = 0; + + while (glyphsLeft > 0) { + + int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); + + // Reached the end of the string or encountered + if (utfChar < 0) { + break; + } + + // Move to the next character in the array + index = nextIndex; + + CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); + + // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage + if (cachedGlyph->mIsValid) { + switch (mode) { + case FRAMEBUFFER: + drawCachedGlyph(cachedGlyph, penX, penY); + break; + case BITMAP: + drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); + break; + case MEASURE: + measureCachedGlyph(cachedGlyph, penX, penY, bounds); + break; + } + } + + penX += (cachedGlyph->mAdvance.x >> 6); + + // If we were given a specific number of glyphs, decrement + if (numGlyphs > 0) { + glyphsLeft --; + } + } +} + +Font::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { + + CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); + if (cachedGlyph == NULL) { + cachedGlyph = cacheGlyph((uint32_t)utfChar); + } + // Is the glyph still in texture cache? + if (!cachedGlyph->mIsValid) { + updateGlyphCache(cachedGlyph); + } + + return cachedGlyph; +} + +void Font::updateGlyphCache(CachedGlyphInfo *glyph) { + FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); + if (error) { + LOGE("Couldn't load glyph."); + return; + } + + glyph->mAdvance = mFace->glyph->advance; + glyph->mBitmapLeft = mFace->glyph->bitmap_left; + glyph->mBitmapTop = mFace->glyph->bitmap_top; + + FT_Bitmap *bitmap = &mFace->glyph->bitmap; + + // Now copy the bitmap into the cache texture + uint32_t startX = 0; + uint32_t startY = 0; + + // Let the font state figure out where to put the bitmap + FontState *state = &mRSC->mStateFont; + glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); + + if (!glyph->mIsValid) { + return; + } + + uint32_t endX = startX + bitmap->width; + uint32_t endY = startY + bitmap->rows; + + glyph->mBitmapMinX = startX; + glyph->mBitmapMinY = startY; + glyph->mBitmapWidth = bitmap->width; + glyph->mBitmapHeight = bitmap->rows; + + uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); + uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); + + glyph->mBitmapMinU = (float)startX / (float)cacheWidth; + glyph->mBitmapMinV = (float)startY / (float)cacheHeight; + glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; + glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; +} + +Font::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { + CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); + mCachedGlyphs.add(glyph, newGlyph); + + newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); + newGlyph->mIsValid = false; + + updateGlyphCache(newGlyph); + + return newGlyph; +} + +Font * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi, + const void *data, uint32_t dataLen) { + rsc->mStateFont.checkInit(); + Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; + + for (uint32_t i = 0; i < activeFonts.size(); i ++) { + Font *ithFont = activeFonts[i]; + if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { + return ithFont; + } + } + + Font *newFont = new Font(rsc); + bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen); + if (isInitialized) { + activeFonts.push(newFont); + rsc->mStateFont.precacheLatin(newFont); + return newFont; + } + + ObjectBase::checkDelete(newFont); + return NULL; +} + +Font::~Font() { + if (mFace) { + FT_Done_Face(mFace); + } + + for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { + if (mRSC->mStateFont.mActiveFonts[ct] == this) { + mRSC->mStateFont.mActiveFonts.removeAt(ct); + break; + } + } + + for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { + CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); + delete glyph; + } +} + +FontState::FontState() { + mInitialized = false; + mMaxNumberOfQuads = 1024; + mCurrentQuadIndex = 0; + mRSC = NULL; + mLibrary = NULL; + + // Get the renderer properties + char property[PROPERTY_VALUE_MAX]; + + // Get the gamma + float gamma = DEFAULT_TEXT_GAMMA; + if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { + gamma = atof(property); + } + + // Get the black gamma threshold + int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; + if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { + blackThreshold = atoi(property); + } + mBlackThreshold = (float)(blackThreshold) / 255.0f; + + // Get the white gamma threshold + int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; + if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { + whiteThreshold = atoi(property); + } + mWhiteThreshold = (float)(whiteThreshold) / 255.0f; + + // Compute the gamma tables + mBlackGamma = gamma; + mWhiteGamma = 1.0f / gamma; + + setFontColor(0.1f, 0.1f, 0.1f, 1.0f); +} + +FontState::~FontState() { + for (uint32_t i = 0; i < mCacheLines.size(); i ++) { + delete mCacheLines[i]; + } + + rsAssert(!mActiveFonts.size()); +} + +FT_Library FontState::getLib() { + if (!mLibrary) { + FT_Error error = FT_Init_FreeType(&mLibrary); + if (error) { + LOGE("Unable to initialize freetype"); + return NULL; + } + } + + return mLibrary; +} + +void FontState::init(Context *rsc) { + mRSC = rsc; +} + +void FontState::flushAllAndInvalidate() { + if (mCurrentQuadIndex != 0) { + issueDrawCommand(); + mCurrentQuadIndex = 0; + } + for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { + mActiveFonts[i]->invalidateTextureCache(); + } + for (uint32_t i = 0; i < mCacheLines.size(); i ++) { + mCacheLines[i]->mCurrentCol = 0; + } +} + +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) { + LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); + return false; + } + + // Now copy the bitmap into the cache texture + uint32_t startX = 0; + uint32_t startY = 0; + + bool bitmapFit = false; + for (uint32_t i = 0; i < mCacheLines.size(); i ++) { + bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); + if (bitmapFit) { + break; + } + } + + // If the new glyph didn't fit, flush the state so far and invalidate everything + if (!bitmapFit) { + flushAllAndInvalidate(); + + // Try to fit it again + for (uint32_t i = 0; i < mCacheLines.size(); i ++) { + bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); + if (bitmapFit) { + break; + } + } + + // if we still don't fit, something is wrong and we shouldn't draw + if (!bitmapFit) { + LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); + return false; + } + } + + *retOriginX = startX; + *retOriginY = startY; + + uint32_t endX = startX + bitmap->width; + uint32_t endY = startY + bitmap->rows; + + uint32_t cacheWidth = getCacheTextureType()->getDimX(); + + uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); + uint8_t *bitmapBuffer = bitmap->buffer; + + uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; + for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { + for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { + uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; + cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; + } + } + + // 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); + mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); + + // Some debug code + /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { + LOGE("Cache Line: H: %u Empty Space: %f", + mCacheLines[i]->mMaxHeight, + (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); + + }*/ + + return true; +} + +void FontState::initRenderState() { + String8 shaderString("varying vec2 varTex0;\n"); + shaderString.append("void main() {\n"); + shaderString.append(" lowp vec4 col = UNI_Color;\n"); + shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); + shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); + shaderString.append(" gl_FragColor = col;\n"); + shaderString.append("}\n"); + + const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); + const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); + mRSC->mStateElement.elementBuilderBegin(); + mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); + mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); + const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); + + Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); + + uint32_t tmp[4]; + tmp[0] = RS_PROGRAM_PARAM_CONSTANT; + tmp[1] = (uint32_t)inputType; + tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; + tmp[3] = RS_TEXTURE_2D; + + mFontShaderFConstant.set(new Allocation(mRSC, inputType, + RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); + ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), + shaderString.length(), tmp, 4); + mFontShaderF.set(pf); + mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); + + Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, + RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); + mFontSampler.set(sampler); + mFontShaderF->bindSampler(mRSC, 0, sampler); + + ProgramStore *fontStore = new ProgramStore(mRSC); + 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); +} + +void FontState::initTextTexture() { + const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); + + // 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); + mTextTexture.set(cacheAlloc); + mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); + + // Split up our cache texture into lines of certain widths + int32_t nextLine = 0; + mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); + nextLine += mCacheLines.top()->mMaxHeight; + mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); + nextLine += mCacheLines.top()->mMaxHeight; + mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); + nextLine += mCacheLines.top()->mMaxHeight; + mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); + nextLine += mCacheLines.top()->mMaxHeight; + mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); + nextLine += mCacheLines.top()->mMaxHeight; + mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); + nextLine += mCacheLines.top()->mMaxHeight; + mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); +} + +// Avoid having to reallocate memory and render quad by quad +void FontState::initVertexArrayBuffers() { + // Now lets write index data + const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); + 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); + uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); + + // Four verts, two triangles , six indices per quad + for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { + int32_t i6 = i * 6; + int32_t i4 = i * 4; + + indexPtr[i6 + 0] = i4 + 0; + indexPtr[i6 + 1] = i4 + 1; + indexPtr[i6 + 2] = i4 + 2; + + indexPtr[i6 + 3] = i4 + 0; + indexPtr[i6 + 4] = i4 + 2; + indexPtr[i6 + 5] = i4 + 3; + } + + indexAlloc->deferedUploadToBufferObject(mRSC); + mIndexBuffer.set(indexAlloc); + + 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); + + mRSC->mStateElement.elementBuilderBegin(); + mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); + mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); + const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); + + Type *vertexDataType = Type::getType(mRSC, vertexDataElem, + mMaxNumberOfQuads * 4, + 0, 0, false, false); + + Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); + mTextMeshPtr = (float*)vertexAlloc->getPtr(); + + mVertexArray.set(vertexAlloc); +} + +// We don't want to allocate anything unless we actually draw text +void FontState::checkInit() { + if (mInitialized) { + return; + } + + initTextTexture(); + initRenderState(); + + initVertexArrayBuffers(); + + // We store a string with letters in a rough frequency of occurrence + mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); + mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); + mLatinPrecache += String8(",.?!()-+@;:`'"); + mLatinPrecache += String8("0123456789"); + + mInitialized = true; +} + +void FontState::issueDrawCommand() { + Context::PushState ps(mRSC); + + mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); + mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); + mRSC->setProgramFragment(mFontShaderF.get()); + mRSC->setProgramStore(mFontProgramStore.get()); + + if (mConstantsDirty) { + mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants)); + mConstantsDirty = false; + } + + if (!mRSC->setupCheck()) { + 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)); +} + +void FontState::appendMeshQuad(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) { + const uint32_t vertsPerQuad = 4; + const uint32_t floatsPerVert = 5; + float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; + + // Cull things that are off the screen + float width = (float)mRSC->getWidth(); + float height = (float)mRSC->getHeight(); + + if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { + return; + } + + /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); + LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); + LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); + LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ + + (*currentPos++) = x1; + (*currentPos++) = y1; + (*currentPos++) = z1; + (*currentPos++) = u1; + (*currentPos++) = v1; + + (*currentPos++) = x2; + (*currentPos++) = y2; + (*currentPos++) = z2; + (*currentPos++) = u2; + (*currentPos++) = v2; + + (*currentPos++) = x3; + (*currentPos++) = y3; + (*currentPos++) = z3; + (*currentPos++) = u3; + (*currentPos++) = v3; + + (*currentPos++) = x4; + (*currentPos++) = y4; + (*currentPos++) = z4; + (*currentPos++) = u4; + (*currentPos++) = v4; + + mCurrentQuadIndex ++; + + if (mCurrentQuadIndex == mMaxNumberOfQuads) { + issueDrawCommand(); + mCurrentQuadIndex = 0; + } +} + +uint32_t FontState::getRemainingCacheCapacity() { + uint32_t remainingCapacity = 0; + uint32_t totalPixels = 0; + for (uint32_t i = 0; i < mCacheLines.size(); i ++) { + remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); + totalPixels += mCacheLines[i]->mMaxWidth; + } + remainingCapacity = (remainingCapacity * 100) / totalPixels; + return remainingCapacity; +} + +void FontState::precacheLatin(Font *font) { + // Remaining capacity is measured in % + uint32_t remainingCapacity = getRemainingCacheCapacity(); + uint32_t precacheIdx = 0; + while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { + font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); + remainingCapacity = getRemainingCacheCapacity(); + precacheIdx ++; + } +} + + +void FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, + uint32_t startIndex, int32_t numGlyphs, + Font::RenderMode mode, + Font::Rect *bounds, + uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { + checkInit(); + + // Render code here + Font *currentFont = mRSC->getFont(); + if (!currentFont) { + if (!mDefault.get()) { + String8 fontsDir("/fonts/DroidSans.ttf"); + String8 fullPath(getenv("ANDROID_ROOT")); + fullPath += fontsDir; + + mDefault.set(Font::create(mRSC, fullPath.string(), 16, 96)); + } + currentFont = mDefault.get(); + } + if (!currentFont) { + LOGE("Unable to initialize any fonts"); + return; + } + + currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, + mode, bounds, bitmap, bitmapW, bitmapH); + + if (mCurrentQuadIndex != 0) { + issueDrawCommand(); + mCurrentQuadIndex = 0; + } +} + +void FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { + renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); + bounds->bottom = - bounds->bottom; + bounds->top = - bounds->top; +} + +void FontState::setFontColor(float r, float g, float b, float a) { + mConstants.mFontColor[0] = r; + mConstants.mFontColor[1] = g; + mConstants.mFontColor[2] = b; + mConstants.mFontColor[3] = a; + + mConstants.mGamma = 1.0f; + const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; + if (luminance <= mBlackThreshold) { + mConstants.mGamma = mBlackGamma; + } else if (luminance >= mWhiteThreshold) { + mConstants.mGamma = mWhiteGamma; + } + + mConstantsDirty = true; +} + +void FontState::getFontColor(float *r, float *g, float *b, float *a) const { + *r = mConstants.mFontColor[0]; + *g = mConstants.mFontColor[1]; + *b = mConstants.mFontColor[2]; + *a = mConstants.mFontColor[3]; +} + +void FontState::deinit(Context *rsc) { + mInitialized = false; + + mFontShaderFConstant.clear(); + + mIndexBuffer.clear(); + mVertexArray.clear(); + + mFontShaderF.clear(); + mFontSampler.clear(); + mFontProgramStore.clear(); + + mTextTexture.clear(); + for (uint32_t i = 0; i < mCacheLines.size(); i ++) { + delete mCacheLines[i]; + } + mCacheLines.clear(); + + mDefault.clear(); + + Vector<Font*> fontsToDereference = mActiveFonts; + for (uint32_t i = 0; i < fontsToDereference.size(); i ++) { + fontsToDereference[i]->zeroUserRef(); + } + + if (mLibrary) { + FT_Done_FreeType( mLibrary ); + mLibrary = NULL; + } +} + +namespace android { +namespace renderscript { + +RsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, uint32_t dpi) { + Font *newFont = Font::create(rsc, name, fontSize, dpi); + if (newFont) { + newFont->incUserRef(); + } + 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); + if (newFont) { + newFont->incUserRef(); + } + return newFont; +} + +} // renderscript +} // android diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h new file mode 100644 index 0000000..00d77c8 --- /dev/null +++ b/libs/rs/rsFont.h @@ -0,0 +1,267 @@ +/* + * 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. + */ + +#ifndef ANDROID_RS_FONT_H +#define ANDROID_RS_FONT_H + +#include "RenderScript.h" +#include "rsStream.h" +#include <utils/String8.h> +#include <utils/Vector.h> +#include <utils/KeyedVector.h> + +#include <ft2build.h> +#include FT_FREETYPE_H + +// --------------------------------------------------------------------------- +namespace android { + +namespace renderscript { + +// Gamma (>= 1.0, <= 10.0) +#define PROPERTY_TEXT_GAMMA "ro.text_gamma" +#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "ro.text_gamma.black_threshold" +#define PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD "ro.text_gamma.white_threshold" + +#define DEFAULT_TEXT_GAMMA 1.4f +#define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64 +#define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192 + +class FontState; + +class Font : public ObjectBase { +public: + enum RenderMode { + FRAMEBUFFER, + BITMAP, + MEASURE, + }; + + struct Rect { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + void set(int32_t l, int32_t r, int32_t t, int32_t b) { + left = l; + right = r; + top = t; + bottom = b; + } + }; + + ~Font(); + + // Currently files do not get serialized, + // but we need to inherit from ObjectBase for ref tracking + virtual void serialize(OStream *stream) const { + } + virtual RsA3DClassID getClassId() const { + return RS_A3D_CLASS_ID_UNKNOWN; + } + + static Font * create(Context *rsc, const char *name, float fontSize, uint32_t dpi, + const void *data = NULL, uint32_t dataLen = 0); + +protected: + + friend class FontState; + + // Pointer to the utf data, length of data, where to start, number of glyphs ot read + // (each glyph may be longer than a char because we are dealing with utf data) + // Last two variables are the initial pen position + void renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, + uint32_t start, int32_t numGlyphs, + RenderMode mode = FRAMEBUFFER, Rect *bounds = NULL, + uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0); + + void invalidateTextureCache(); + struct CachedGlyphInfo + { + // Has the cache been invalidated? + bool mIsValid; + // Location of the cached glyph in the bitmap + // in case we need to resize the texture + uint32_t mBitmapMinX; + uint32_t mBitmapMinY; + uint32_t mBitmapWidth; + uint32_t mBitmapHeight; + // Also cache texture coords for the quad + float mBitmapMinU; + float mBitmapMinV; + float mBitmapMaxU; + float mBitmapMaxV; + // Minimize how much we call freetype + FT_UInt mGlyphIndex; + FT_Vector mAdvance; + // Values below contain a glyph's origin in the bitmap + FT_Int mBitmapLeft; + FT_Int mBitmapTop; + }; + + String8 mFontName; + float mFontSize; + uint32_t mDpi; + + Font(Context *rsc); + bool init(const char *name, float fontSize, uint32_t dpi, const void *data = NULL, uint32_t dataLen = 0); + + FT_Face mFace; + bool mInitialized; + bool mHasKerning; + + DefaultKeyedVector<uint32_t, CachedGlyphInfo* > mCachedGlyphs; + CachedGlyphInfo* getCachedUTFChar(int32_t utfChar); + + CachedGlyphInfo *cacheGlyph(uint32_t glyph); + void updateGlyphCache(CachedGlyphInfo *glyph); + void measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds); + void drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y); + void drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, + uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH); +}; + +class FontState { +public: + FontState(); + ~FontState(); + + void init(Context *rsc); + void deinit(Context *rsc); + + ObjectBaseRef<Font> mDefault; + ObjectBaseRef<Font> mLast; + + void renderText(const char *text, uint32_t len, int32_t x, int32_t y, + uint32_t startIndex = 0, int numGlyphs = -1, + Font::RenderMode mode = Font::FRAMEBUFFER, + Font::Rect *bounds = NULL, + uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0); + + void measureText(const char *text, uint32_t len, Font::Rect *bounds); + + void setFontColor(float r, float g, float b, float a); + void getFontColor(float *r, float *g, float *b, float *a) const; + +protected: + + friend class Font; + + struct CacheTextureLine { + uint32_t mMaxHeight; + uint32_t mMaxWidth; + uint32_t mCurrentRow; + uint32_t mCurrentCol; + bool mDirty; + + CacheTextureLine(uint32_t maxHeight, uint32_t maxWidth, uint32_t currentRow, uint32_t currentCol) + : mMaxHeight(maxHeight), mMaxWidth(maxWidth), mCurrentRow(currentRow), + mCurrentCol(currentCol), mDirty(false) { + } + + bool fitBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { + if ((uint32_t)bitmap->rows > mMaxHeight) { + return false; + } + + if (mCurrentCol + (uint32_t)bitmap->width < mMaxWidth) { + *retOriginX = mCurrentCol; + *retOriginY = mCurrentRow; + mCurrentCol += bitmap->width; + mDirty = true; + return true; + } + + return false; + } + }; + + Vector<CacheTextureLine*> mCacheLines; + uint32_t getRemainingCacheCapacity(); + + void precacheLatin(Font *font); + String8 mLatinPrecache; + + Context *mRSC; + + struct { + float mFontColor[4]; + float mGamma; + } mConstants; + bool mConstantsDirty; + + float mBlackGamma; + float mWhiteGamma; + + float mBlackThreshold; + float mWhiteThreshold; + + // Free type library, we only need one copy + FT_Library mLibrary; + FT_Library getLib(); + Vector<Font*> mActiveFonts; + + // Render state for the font + ObjectBaseRef<Allocation> mFontShaderFConstant; + ObjectBaseRef<ProgramFragment> mFontShaderF; + ObjectBaseRef<Sampler> mFontSampler; + ObjectBaseRef<ProgramStore> mFontProgramStore; + void initRenderState(); + + // Texture to cache glyph bitmaps + ObjectBaseRef<Allocation> mTextTexture; + void initTextTexture(); + const uint8_t* getTextTextureData() const { + return (uint8_t*)mTextTexture->getPtr(); + } + + bool cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY); + const Type* getCacheTextureType() { + return mTextTexture->getType(); + } + + void flushAllAndInvalidate(); + + // Pointer to vertex data to speed up frame to frame work + float *mTextMeshPtr; + uint32_t mCurrentQuadIndex; + uint32_t mMaxNumberOfQuads; + + void initVertexArrayBuffers(); + ObjectBaseRef<Allocation> mIndexBuffer; + ObjectBaseRef<Allocation> mVertexArray; + + + bool mInitialized; + + void checkInit(); + + void issueDrawCommand(); + + void appendMeshQuad(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); +}; + +} +} + +#endif diff --git a/libs/rs/rsHandcode.h b/libs/rs/rsHandcode.h index 800eddd..6f21a35 100644 --- a/libs/rs/rsHandcode.h +++ b/libs/rs/rsHandcode.h @@ -1,47 +1,97 @@ #define DATA_SYNC_SIZE 1024 -static inline void rsHCAPI_AllocationData (RsContext rsc, RsAllocation va, const void * data, uint32_t sizeBytes) -{ +static inline void rsHCAPI_ContextFinish (RsContext rsc) { ThreadIO *io = &((Context *)rsc)->mIO; - uint32_t size = sizeof(RS_CMD_AllocationData); + uint32_t size = sizeof(RS_CMD_ContextFinish); + RS_CMD_ContextFinish *cmd = static_cast<RS_CMD_ContextFinish *>(io->mToCore.reserve(size)); + 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_AllocationData *cmd = static_cast<RS_CMD_AllocationData *>(io->mToCore.reserve(size)); - cmd->va = va; - cmd->bytes = sizeBytes; + 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_AllocationData, size); + io->mToCore.commit(RS_CMD_ID_ScriptInvokeV, size); } else { - io->mToCore.commitSync(RS_CMD_ID_AllocationData, size); + io->mToCore.commitSync(RS_CMD_ID_ScriptInvokeV, size); } } -static inline void rsHCAPI_Allocation1DSubData (RsContext rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void * data, uint32_t sizeBytes) -{ +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_Allocation1DSubData); + uint32_t size = sizeof(RS_CMD_Allocation1DData); if (sizeBytes < DATA_SYNC_SIZE) { size += (sizeBytes + 3) & ~3; } - RS_CMD_Allocation1DSubData *cmd = static_cast<RS_CMD_Allocation1DSubData *>(io->mToCore.reserve(size)); + 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_Allocation1DSubData, size); + io->mToCore.commit(RS_CMD_ID_Allocation1DData, size); } else { - io->mToCore.commitSync(RS_CMD_ID_Allocation1DSubData, size); + 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/rsLight.cpp b/libs/rs/rsLight.cpp deleted file mode 100644 index 6f2cf3e..0000000 --- a/libs/rs/rsLight.cpp +++ /dev/null @@ -1,130 +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 "rsContext.h" - -#include <GLES/gl.h> - -using namespace android; -using namespace android::renderscript; - - -Light::Light(Context *rsc, bool isLocal, bool isMono) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; - mIsLocal = isLocal; - mIsMono = isMono; - - mPosition[0] = 0; - mPosition[1] = 0; - mPosition[2] = 1; - mPosition[3] = 0; - - mColor[0] = 1.f; - mColor[1] = 1.f; - mColor[2] = 1.f; - mColor[3] = 1.f; -} - -Light::~Light() -{ -} - -void Light::setPosition(float x, float y, float z) -{ - mPosition[0] = x; - mPosition[1] = y; - mPosition[2] = z; -} - -void Light::setColor(float r, float g, float b) -{ - mColor[0] = r; - mColor[1] = g; - mColor[2] = b; -} - -void Light::setupGL(uint32_t num) const -{ - glLightfv(GL_LIGHT0 + num, GL_DIFFUSE, mColor); - glLightfv(GL_LIGHT0 + num, GL_SPECULAR, mColor); - glLightfv(GL_LIGHT0 + num, GL_POSITION, mPosition); -} - -//////////////////////////////////////////// - -LightState::LightState() -{ - clear(); -} - -LightState::~LightState() -{ -} - -void LightState::clear() -{ - mIsLocal = false; - mIsMono = false; -} - - -//////////////////////////////////////////////////// -// - -namespace android { -namespace renderscript { - -void rsi_LightBegin(Context *rsc) -{ - rsc->mStateLight.clear(); -} - -void rsi_LightSetLocal(Context *rsc, bool isLocal) -{ - rsc->mStateLight.mIsLocal = isLocal; -} - -void rsi_LightSetMonochromatic(Context *rsc, bool isMono) -{ - rsc->mStateLight.mIsMono = isMono; -} - -RsLight rsi_LightCreate(Context *rsc) -{ - Light *l = new Light(rsc, rsc->mStateLight.mIsLocal, - rsc->mStateLight.mIsMono); - l->incUserRef(); - return l; -} - -void rsi_LightSetColor(Context *rsc, RsLight vl, float r, float g, float b) -{ - Light *l = static_cast<Light *>(vl); - l->setColor(r, g, b); -} - -void rsi_LightSetPosition(Context *rsc, RsLight vl, float x, float y, float z) -{ - Light *l = static_cast<Light *>(vl); - l->setPosition(x, y, z); -} - - - -} -} diff --git a/libs/rs/rsLight.h b/libs/rs/rsLight.h deleted file mode 100644 index d8796e6..0000000 --- a/libs/rs/rsLight.h +++ /dev/null @@ -1,64 +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. - */ - -#ifndef ANDROID_LIGHT_H -#define ANDROID_LIGHT_H - - -#include "rsObjectBase.h" - -// --------------------------------------------------------------------------- -namespace android { -namespace renderscript { - - -// An element is a group of Components that occupies one cell in a structure. -class Light : public ObjectBase -{ -public: - Light(Context *, bool isLocal, bool isMono); - virtual ~Light(); - - // Values, mutable after creation. - void setPosition(float x, float y, float z); - void setColor(float r, float g, float b); - - void setupGL(uint32_t num) const; - -protected: - float mColor[4]; - float mPosition[4]; - bool mIsLocal; - bool mIsMono; -}; - - -class LightState { -public: - LightState(); - ~LightState(); - - void clear(); - - bool mIsMono; - bool mIsLocal; -}; - - -} -} -#endif //ANDROID_LIGHT_H - diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp index c796520..3f88543 100644 --- a/libs/rs/rsLocklessFifo.cpp +++ b/libs/rs/rsLocklessFifo.cpp @@ -15,30 +15,28 @@ */ #include "rsLocklessFifo.h" +#include "utils/Timers.h" +#include "utils/StopWatch.h" using namespace android; +using namespace android::renderscript; - -LocklessCommandFifo::LocklessCommandFifo() -{ +LocklessCommandFifo::LocklessCommandFifo() { } -LocklessCommandFifo::~LocklessCommandFifo() -{ +LocklessCommandFifo::~LocklessCommandFifo() { if (!mInShutdown) { shutdown(); } free(mBuffer); } -void LocklessCommandFifo::shutdown() -{ +void LocklessCommandFifo::shutdown() { mInShutdown = true; mSignalToWorker.set(); } -bool LocklessCommandFifo::init(uint32_t sizeInBytes) -{ +bool LocklessCommandFifo::init(uint32_t sizeInBytes) { // Add room for a buffer reset command mBuffer = static_cast<uint8_t *>(malloc(sizeInBytes + 4)); if (!mBuffer) { @@ -61,8 +59,7 @@ bool LocklessCommandFifo::init(uint32_t sizeInBytes) return true; } -uint32_t LocklessCommandFifo::getFreeSpace() const -{ +uint32_t LocklessCommandFifo::getFreeSpace() const { int32_t freeSpace = 0; //dumpState("getFreeSpace"); @@ -78,14 +75,13 @@ uint32_t LocklessCommandFifo::getFreeSpace() const return freeSpace; } -bool LocklessCommandFifo::isEmpty() const -{ - return mPut == mGet; +bool LocklessCommandFifo::isEmpty() const { + uint32_t p = android_atomic_acquire_load((int32_t *)&mPut); + return ((uint8_t *)p) == mGet; } -void * LocklessCommandFifo::reserve(uint32_t sizeInBytes) -{ +void * LocklessCommandFifo::reserve(uint32_t sizeInBytes) { // Add space for command header and loop token; sizeInBytes += 8; @@ -97,8 +93,7 @@ void * LocklessCommandFifo::reserve(uint32_t sizeInBytes) return mPut + 4; } -void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes) -{ +void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes) { if (mInShutdown) { return; } @@ -110,33 +105,37 @@ void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes) mSignalToWorker.set(); } -void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes) -{ +void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes) { if (mInShutdown) { return; } + + //char buf[1024]; + //sprintf(buf, "RenderScript LocklessCommandFifo::commitSync %p %i %i", this, command, sizeInBytes); + //StopWatch compileTimer(buf); commit(command, sizeInBytes); flush(); } -void LocklessCommandFifo::flush() -{ +void LocklessCommandFifo::flush() { //dumpState("flush 1"); - while(mPut != mGet) { + while (mPut != mGet) { mSignalToControl.wait(); } //dumpState("flush 2"); } -const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData) -{ - while(1) { - //dumpState("get"); - while(isEmpty() && !mInShutdown) { - mSignalToControl.set(); - mSignalToWorker.wait(); - } +void LocklessCommandFifo::wait() { + while (isEmpty() && !mInShutdown) { + mSignalToControl.set(); + mSignalToWorker.wait(); + } +} +const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData) { + while (1) { + //dumpState("get"); + wait(); if (mInShutdown) { *command = 0; *bytesData = 0; @@ -155,116 +154,78 @@ const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData) } } -void LocklessCommandFifo::next() -{ +void LocklessCommandFifo::next() { uint32_t bytes = reinterpret_cast<const uint16_t *>(mGet)[1]; - mGet += ((bytes + 3) & ~3) + 4; + + android_atomic_add(((bytes + 3) & ~3) + 4, (int32_t *)&mGet); + //mGet += ((bytes + 3) & ~3) + 4; if (isEmpty()) { mSignalToControl.set(); } //dumpState("next"); } -void LocklessCommandFifo::makeSpace(uint32_t bytes) -{ - //dumpState("make space"); +bool LocklessCommandFifo::makeSpaceNonBlocking(uint32_t bytes) { + //dumpState("make space non-blocking"); if ((mPut+bytes) > mEnd) { // Need to loop regardless of where get is. - while((mGet > mPut) && (mBuffer+4 >= mGet)) { - usleep(100); + if ((mGet > mPut) || (mBuffer+4 >= mGet)) { + return false; } // Toss in a reset then the normal wait for space will do the rest. reinterpret_cast<uint16_t *>(mPut)[0] = 0; reinterpret_cast<uint16_t *>(mPut)[1] = 0; mPut = mBuffer; + mSignalToWorker.set(); } // it will fit here so we just need to wait for space. - while(getFreeSpace() < bytes) { - usleep(100); - } - -} - -void LocklessCommandFifo::dumpState(const char *s) const -{ - LOGV("%s put %p, get %p, buf %p, end %p", s, mPut, mGet, mBuffer, mEnd); -} - -LocklessCommandFifo::Signal::Signal() -{ - mSet = true; -} - -LocklessCommandFifo::Signal::~Signal() -{ - pthread_mutex_destroy(&mMutex); - pthread_cond_destroy(&mCondition); -} - -bool LocklessCommandFifo::Signal::init() -{ - int status = pthread_mutex_init(&mMutex, NULL); - if (status) { - LOGE("LocklessFifo mutex init failure"); - return false; - } - - status = pthread_cond_init(&mCondition, NULL); - if (status) { - LOGE("LocklessFifo condition init failure"); - pthread_mutex_destroy(&mMutex); + if (getFreeSpace() < bytes) { return false; } return true; } -void LocklessCommandFifo::Signal::set() -{ - int status; +void LocklessCommandFifo::makeSpace(uint32_t bytes) { + //dumpState("make space"); + if ((mPut+bytes) > mEnd) { + // Need to loop regardless of where get is. + while ((mGet > mPut) || (mBuffer+4 >= mGet)) { + usleep(100); + } - status = pthread_mutex_lock(&mMutex); - if (status) { - LOGE("LocklessCommandFifo: error %i locking for set condition.", status); - return; + // Toss in a reset then the normal wait for space will do the rest. + reinterpret_cast<uint16_t *>(mPut)[0] = 0; + reinterpret_cast<uint16_t *>(mPut)[1] = 0; + mPut = mBuffer; + mSignalToWorker.set(); } - mSet = true; - - status = pthread_cond_signal(&mCondition); - if (status) { - LOGE("LocklessCommandFifo: error %i on set condition.", status); + // it will fit here so we just need to wait for space. + while (getFreeSpace() < bytes) { + usleep(100); } - status = pthread_mutex_unlock(&mMutex); - if (status) { - LOGE("LocklessCommandFifo: error %i unlocking for set condition.", status); - } } -void LocklessCommandFifo::Signal::wait() -{ - int status; +void LocklessCommandFifo::dumpState(const char *s) const { + LOGV("%s %p put %p, get %p, buf %p, end %p", s, this, mPut, mGet, mBuffer, mEnd); +} - status = pthread_mutex_lock(&mMutex); - if (status) { - LOGE("LocklessCommandFifo: error %i locking for condition.", status); - return; +void LocklessCommandFifo::printDebugData() const { + dumpState("printing fifo debug"); + const uint32_t *pptr = (const uint32_t *)mGet; + pptr -= 8 * 4; + if (mGet < mBuffer) { + pptr = (const uint32_t *)mBuffer; } - if (!mSet) { - status = pthread_cond_wait(&mCondition, &mMutex); - if (status) { - LOGE("LocklessCommandFifo: error %i waiting on condition.", status); - } - } - mSet = false; - status = pthread_mutex_unlock(&mMutex); - if (status) { - LOGE("LocklessCommandFifo: error %i unlocking for condition.", status); + for (int ct=0; ct < 16; ct++) { + LOGV("fifo %p = 0x%08x 0x%08x 0x%08x 0x%08x", pptr, pptr[0], pptr[1], pptr[2], pptr[3]); + pptr += 4; } -} +} diff --git a/libs/rs/rsLocklessFifo.h b/libs/rs/rsLocklessFifo.h index d0a4356..eabdc3e 100644 --- a/libs/rs/rsLocklessFifo.h +++ b/libs/rs/rsLocklessFifo.h @@ -19,8 +19,10 @@ #include "rsUtils.h" +#include "rsSignal.h" namespace android { +namespace renderscript { // A simple FIFO to be used as a producer / consumer between two @@ -28,33 +30,17 @@ namespace android { // will not require locking. It is not threadsafe for multiple // readers or writers by design. -class LocklessCommandFifo -{ +class LocklessCommandFifo { public: bool init(uint32_t size); void shutdown(); + void printDebugData() const; + LocklessCommandFifo(); ~LocklessCommandFifo(); - protected: - class Signal { - public: - Signal(); - ~Signal(); - - bool init(); - - void set(); - void wait(); - - protected: - bool mSet; - pthread_mutex_t mMutex; - pthread_cond_t mCondition; - }; - uint8_t * volatile mPut; uint8_t * volatile mGet; uint8_t * mBuffer; @@ -65,27 +51,28 @@ protected: Signal mSignalToWorker; Signal mSignalToControl; - - public: void * reserve(uint32_t bytes); void commit(uint32_t command, uint32_t bytes); void commitSync(uint32_t command, uint32_t bytes); void flush(); + void wait(); + const void * get(uint32_t *command, uint32_t *bytesData); void next(); void makeSpace(uint32_t bytes); + bool makeSpaceNonBlocking(uint32_t bytes); bool isEmpty() const; uint32_t getFreeSpace() const; - private: void dumpState(const char *) const; }; } +} #endif diff --git a/libs/rs/rsMatrix.cpp b/libs/rs/rsMatrix.cpp index 2f21405..ca41886 100644 --- a/libs/rs/rsMatrix.cpp +++ b/libs/rs/rsMatrix.cpp @@ -23,10 +23,7 @@ using namespace android; using namespace android::renderscript; - - -void Matrix::loadIdentity() -{ +void Matrix::loadIdentity() { set(0, 0, 1); set(1, 0, 0); set(2, 0, 0); @@ -48,18 +45,15 @@ void Matrix::loadIdentity() set(3, 3, 1); } -void Matrix::load(const float *v) -{ +void Matrix::load(const float *v) { memcpy(m, v, sizeof(m)); } -void Matrix::load(const Matrix *v) -{ +void Matrix::load(const Matrix *v) { memcpy(m, v->m, sizeof(m)); } -void Matrix::loadRotate(float rot, float x, float y, float z) -{ +void Matrix::loadRotate(float rot, float x, float y, float z) { float c, s; m[3] = 0; m[7] = 0; @@ -73,7 +67,7 @@ void Matrix::loadRotate(float rot, float x, float y, float z) s = sinf(rot); const float len = sqrtf(x*x + y*y + z*z); - if (!(len != 1)) { + if (len != 1) { const float recipLen = 1.f / len; x *= recipLen; y *= recipLen; @@ -97,24 +91,21 @@ void Matrix::loadRotate(float rot, float x, float y, float z) m[10] = z*z*nc + c; } -void Matrix::loadScale(float x, float y, float z) -{ +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) -{ +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) -{ +void Matrix::loadMultiply(const Matrix *lhs, const Matrix *rhs) { for (int i=0 ; i<4 ; i++) { float ri0 = 0; float ri1 = 0; diff --git a/libs/rs/rsMatrix.h b/libs/rs/rsMatrix.h index 11ce42e..4130b8e 100644 --- a/libs/rs/rsMatrix.h +++ b/libs/rs/rsMatrix.h @@ -23,8 +23,7 @@ namespace android { namespace renderscript { -struct Matrix -{ +struct Matrix { float m[16]; inline float get(int i, int j) const { @@ -69,13 +68,8 @@ struct Matrix tmp.loadTranslate(x, y, z); multiply(&tmp); } - - - }; - - } } diff --git a/libs/rs/rsMesh.cpp b/libs/rs/rsMesh.cpp index d595b4e..baf4c53 100644 --- a/libs/rs/rsMesh.cpp +++ b/libs/rs/rsMesh.cpp @@ -14,35 +14,417 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" -using namespace android; -using namespace android::renderscript; - #include <GLES/gl.h> +#include <GLES2/gl2.h> #include <GLES/glext.h> +#else +#include "rsContextHostStub.h" + +#include <OpenGL/gl.h> +#include <OpenGl/glext.h> +#endif + +using namespace android; +using namespace android::renderscript; -Mesh::Mesh(Context *rsc) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; - mVerticies = NULL; - mVerticiesCount = 0; +Mesh::Mesh(Context *rsc) : ObjectBase(rsc) { mPrimitives = NULL; mPrimitivesCount = 0; + mVertexBuffers = NULL; + mVertexBufferCount = 0; + mAttribs = NULL; + mAttribAllocationIndex = NULL; + + mAttribCount = 0; } -Mesh::~Mesh() -{ +Mesh::~Mesh() { + if (mVertexBuffers) { + delete[] mVertexBuffers; + } + + if (mPrimitives) { + for (uint32_t i = 0; i < mPrimitivesCount; i ++) { + delete mPrimitives[i]; + } + delete[] mPrimitives; + } + + if (mAttribs) { + delete[] mAttribs; + delete[] mAttribAllocationIndex; + } } +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; + } -MeshContext::MeshContext() -{ + return true; } -MeshContext::~MeshContext() -{ +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 ++; + } + } + } + + if (mAttribs) { + delete [] mAttribs; + delete [] mAttribAllocationIndex; + mAttribs = NULL; + mAttribAllocationIndex = NULL; + } + if (!mAttribCount) { + return; + } + + 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 ++; + } + } } +void Mesh::render(Context *rsc) const { + for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) { + renderPrimitive(rsc, ct); + } +} + +void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const { + if (primIndex >= mPrimitivesCount) { + LOGE("Invalid primitive index"); + return; + } + + Primitive_t *prim = mPrimitives[primIndex]; + + if (prim->mIndexBuffer.get()) { + renderPrimitiveRange(rsc, primIndex, 0, prim->mIndexBuffer->getType()->getDimX()); + return; + } + + renderPrimitiveRange(rsc, primIndex, 0, mVertexBuffers[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) { + 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"); +} + + +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); + } + } +} + +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; + } + } +} + +void Mesh::serialize(OStream *stream) const { + // Need to identify ourselves + stream->addU32((uint32_t)getClassId()); + + String8 name(getName()); + 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(mPrimitivesCount); + // Store the primitives + for (uint32_t pCount = 0; pCount < mPrimitivesCount; pCount ++) { + Primitive_t * prim = mPrimitives[pCount]; + + stream->addU8((uint8_t)prim->mPrimitive); + + if (prim->mIndexBuffer.get()) { + stream->addU32(1); + prim->mIndexBuffer->serialize(stream); + } else { + stream->addU32(0); + } + } +} + +Mesh *Mesh::createFromStream(Context *rsc, IStream *stream) { + // First make sure we are reading the correct object + RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); + if (classID != RS_A3D_CLASS_ID_MESH) { + LOGE("mesh loading skipped due to invalid class id"); + 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]; + + for (uint32_t vCount = 0; vCount < mesh->mVertexBufferCount; vCount ++) { + Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream); + mesh->mVertexBuffers[vCount].set(vertexAlloc); + } + } + + mesh->mPrimitivesCount = stream->loadU32(); + if (mesh->mPrimitivesCount) { + mesh->mPrimitives = new Primitive_t *[mesh->mPrimitivesCount]; + + // 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(); + + // 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); + } + } + } + + mesh->updateGLPrimitives(); + mesh->initVertexAttribs(); + mesh->uploadAll(rsc); + + return mesh; +} + +void Mesh::computeBBox() { + float *posPtr = NULL; + uint32_t vectorSize = 0; + 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(); + const Element *bufferElem = bufferType->getElement(); + + for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) { + if (strcmp(bufferElem->getFieldName(ct), "position") == 0) { + 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); + numVerts = bufferType->getDimX(); + break; + } + } + if (posPtr) { + break; + } + } + + mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6; + mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6; + if (!posPtr) { + LOGE("Unable to compute bounding box"); + mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f; + mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f; + return; + } + + for (uint32_t i = 0; i < numVerts; i ++) { + for (uint32_t v = 0; v < vectorSize; v ++) { + mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]); + mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]); + } + posPtr += stride; + } +} + + +MeshContext::MeshContext() { +} + +MeshContext::~MeshContext() { +} + +namespace android { +namespace renderscript { + +RsMesh rsi_MeshCreate(Context *rsc, uint32_t vtxCount, uint32_t idxCount) { + Mesh *sm = new Mesh(rsc); + 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; + } + + 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); + + sm->mPrimitives[slot]->mIndexBuffer.set((Allocation *)va); + sm->mPrimitives[slot]->mPrimitive = (RsPrimitive)primType; + sm->updateGLPrimitives(); +} + +void rsi_MeshInitVertexAttribs(Context *rsc, RsMesh mv) { + Mesh *sm = static_cast<Mesh *>(mv); + sm->initVertexAttribs(); +} + +}} + +void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) { + Mesh *sm = static_cast<Mesh *>(mv); + *numVtx = sm->mVertexBufferCount; +} + +void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) { + Mesh *sm = static_cast<Mesh *>(mv); + *numIdx = sm->mPrimitivesCount; +} + +void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) { + Mesh *sm = static_cast<Mesh *>(mv); + rsAssert(vtxDataCount == sm->mVertexBufferCount); + + for (uint32_t ct = 0; ct < vtxDataCount; ct ++) { + vtxData[ct] = sm->mVertexBuffers[ct].get(); + sm->mVertexBuffers[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); + + 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(); + } + } +} diff --git a/libs/rs/rsMesh.h b/libs/rs/rsMesh.h index 5201abd..410b70b 100644 --- a/libs/rs/rsMesh.h +++ b/libs/rs/rsMesh.h @@ -26,65 +26,67 @@ namespace renderscript { // An element is a group of Components that occupies one cell in a structure. -class Mesh : public ObjectBase -{ +class Mesh : public ObjectBase { public: Mesh(Context *); ~Mesh(); - struct Verticies_t - { - Allocation ** mAllocations; - uint32_t mAllocationCount; - - size_t mVertexDataSize; - - size_t mOffsetCoord; - size_t mOffsetTex; - size_t mOffsetNorm; - - size_t mSizeCoord; - size_t mSizeTex; - size_t mSizeNorm; - - uint32_t mBufferObject; - }; + // 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 { - RsPrimitive mType; - Verticies_t *mVerticies; - - uint32_t mIndexCount; - uint16_t *mIndicies; + ObjectBaseRef<Allocation> mIndexBuffer; - uint32_t mRestartCounts; - uint16_t *mRestarts; + RsPrimitive mPrimitive; + uint32_t mGLPrimitive; }; - Verticies_t * mVerticies; - uint32_t mVerticiesCount; - Primitive_t ** mPrimitives; uint32_t mPrimitivesCount; + 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(); + + virtual void serialize(OStream *stream) const; + virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_MESH; } + static Mesh *createFromStream(Context *rsc, IStream *stream); + + // Bounding volumes + float mBBoxMin[3]; + float mBBoxMax[3]; + void computeBBox(); + void initVertexAttribs(); - void analyzeElement(); 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; }; -class MeshContext -{ +class MeshContext { public: MeshContext(); ~MeshContext(); - }; - } } #endif //ANDROID_RS_TRIANGLE_MESH_H + diff --git a/libs/rs/rsMutex.cpp b/libs/rs/rsMutex.cpp new file mode 100644 index 0000000..2105288 --- /dev/null +++ b/libs/rs/rsMutex.cpp @@ -0,0 +1,59 @@ +/* + * 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 "rsMutex.h" + +using namespace android; +using namespace android::renderscript; + + +Mutex::Mutex() { +} + +Mutex::~Mutex() { + pthread_mutex_destroy(&mMutex); +} + +bool Mutex::init() { + int status = pthread_mutex_init(&mMutex, NULL); + if (status) { + LOGE("Mutex::Mutex init failure"); + return false; + } + return true; +} + +bool Mutex::lock() { + int status; + status = pthread_mutex_lock(&mMutex); + if (status) { + LOGE("Mutex: error %i locking.", status); + return false; + } + return true; +} + +bool Mutex::unlock() { + int status; + status = pthread_mutex_unlock(&mMutex); + if (status) { + LOGE("Mutex error %i unlocking.", status); + return false; + } + return true; +} + + diff --git a/libs/rs/rsNoise.h b/libs/rs/rsMutex.h index 9040751..47725d7 100644 --- a/libs/rs/rsNoise.h +++ b/libs/rs/rsMutex.h @@ -14,22 +14,30 @@ * limitations under the License. */ -#ifndef ANDROID_RS_NOISE_H -#define ANDROID_RS_NOISE_H +#ifndef ANDROID_RS_MUTEX_H +#define ANDROID_RS_MUTEX_H + + +#include "rsUtils.h" -// --------------------------------------------------------------------------- namespace android { namespace renderscript { -void SC_normalizef2(float v[]); -void SC_normalizef3(float v[]); -float SC_noisef(float x); -float SC_noisef2(float x, float y); -float SC_noisef3(float x, float y, float z); -float SC_turbulencef2(float x, float y, float octaves); -float SC_turbulencef3(float x, float y, float z, float octaves); +class Mutex { +public: + Mutex(); + ~Mutex(); + + bool init(); + bool lock(); + bool unlock(); + +protected: + pthread_mutex_t mMutex; +}; } } #endif + diff --git a/libs/rs/rsNoise.cpp b/libs/rs/rsNoise.cpp deleted file mode 100644 index 4b67586..0000000 --- a/libs/rs/rsNoise.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * This implementation of the noise functions was ported from the Java - * implementation by Jerry Huxtable (http://www.jhlabs.com) under - * Apache License 2.0 (see http://jhlabs.com/ip/filters/download.html) - * - * Original header: - * - * Copyright 2006 Jerry Huxtable - * - * 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 "rsNoise.h" - -#include <math.h> -#include <stdlib.h> -#include <time.h> - -namespace android { -namespace renderscript { - -#define B 0x100 -#define BM 0xff -#define N 0x1000 - -static int p[B + B + 2]; -static float g3[B + B + 2][3]; -static float g2[B + B + 2][2]; -static float g1[B + B + 2]; -static bool noise_start = true; - -#define lerpf(start, stop, amount) start + (stop - start) * amount - -static inline float noise_sCurve(float t) -{ - return t * t * (3.0f - 2.0f * t); -} - -inline void SC_normalizef2(float v[]) -{ - float s = (float)sqrtf(v[0] * v[0] + v[1] * v[1]); - v[0] = v[0] / s; - v[1] = v[1] / s; -} - -inline void SC_normalizef3(float v[]) -{ - float s = (float)sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); - v[0] = v[0] / s; - v[1] = v[1] / s; - v[2] = v[2] / s; -} - -static void noise_init() -{ - int i, j, k; - - for (i = 0; i < B; i++) { - p[i] = i; - - g1[i] = (float)((rand() % (B + B)) - B) / B; - - for (j = 0; j < 2; j++) - g2[i][j] = (float)((rand() % (B + B)) - B) / B; - SC_normalizef2(g2[i]); - - for (j = 0; j < 3; j++) - g3[i][j] = (float)((rand() % (B + B)) - B) / B; - SC_normalizef3(g3[i]); - } - - for (i = B-1; i >= 0; i--) { - k = p[i]; - p[i] = p[j = rand() % B]; - p[j] = k; - } - - for (i = 0; i < B + 2; i++) { - p[B + i] = p[i]; - g1[B + i] = g1[i]; - for (j = 0; j < 2; j++) - g2[B + i][j] = g2[i][j]; - for (j = 0; j < 3; j++) - g3[B + i][j] = g3[i][j]; - } -} - -float SC_noisef(float x) -{ - srand(time(NULL)); - int bx0, bx1; - float rx0, rx1, sx, t, u, v; - - if (noise_start) { - noise_start = false; - noise_init(); - } - - t = x + N; - bx0 = ((int)t) & BM; - bx1 = (bx0+1) & BM; - rx0 = t - (int)t; - rx1 = rx0 - 1.0f; - - sx = noise_sCurve(rx0); - - u = rx0 * g1[p[bx0]]; - v = rx1 * g1[p[bx1]]; - return 2.3f * lerpf(u, v, sx); -} - -float SC_noisef2(float x, float y) -{ - srand(time(NULL)); - int bx0, bx1, by0, by1, b00, b10, b01, b11; - float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v; - float *q; - int i, j; - - if (noise_start) { - noise_start = false; - noise_init(); - } - - t = x + N; - bx0 = ((int)t) & BM; - bx1 = (bx0+1) & BM; - rx0 = t - (int)t; - rx1 = rx0 - 1.0f; - - t = y + N; - by0 = ((int)t) & BM; - by1 = (by0+1) & BM; - ry0 = t - (int)t; - ry1 = ry0 - 1.0f; - - i = p[bx0]; - j = p[bx1]; - - b00 = p[i + by0]; - b10 = p[j + by0]; - b01 = p[i + by1]; - b11 = p[j + by1]; - - sx = noise_sCurve(rx0); - sy = noise_sCurve(ry0); - - q = g2[b00]; u = rx0 * q[0] + ry0 * q[1]; - q = g2[b10]; v = rx1 * q[0] + ry0 * q[1]; - a = lerpf(u, v, sx); - - q = g2[b01]; u = rx0 * q[0] + ry1 * q[1]; - q = g2[b11]; v = rx1 * q[0] + ry1 * q[1]; - b = lerpf(u, v, sx); - - return 1.5f*lerpf(a, b, sy); -} - -float SC_noisef3(float x, float y, float z) -{ - srand(time(NULL)); - int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; - float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v; - float *q; - int i, j; - - if (noise_start) { - noise_start = false; - noise_init(); - } - - t = x + N; - bx0 = ((int)t) & BM; - bx1 = (bx0+1) & BM; - rx0 = t - (int)t; - rx1 = rx0 - 1.0f; - - t = y + N; - by0 = ((int)t) & BM; - by1 = (by0+1) & BM; - ry0 = t - (int)t; - ry1 = ry0 - 1.0f; - - t = z + N; - bz0 = ((int)t) & BM; - bz1 = (bz0+1) & BM; - rz0 = t - (int)t; - rz1 = rz0 - 1.0f; - - i = p[bx0]; - j = p[bx1]; - - b00 = p[i + by0]; - b10 = p[j + by0]; - b01 = p[i + by1]; - b11 = p[j + by1]; - - t = noise_sCurve(rx0); - sy = noise_sCurve(ry0); - sz = noise_sCurve(rz0); - - q = g3[b00 + bz0]; u = rx0 * q[0] + ry0 * q[1] + rz0 * q[2]; - q = g3[b10 + bz0]; v = rx1 * q[0] + ry0 * q[1] + rz0 * q[2]; - a = lerpf(u, v, t); - - q = g3[b01 + bz0]; u = rx0 * q[0] + ry1 * q[1] + rz0 * q[2]; - q = g3[b11 + bz0]; v = rx1 * q[0] + ry1 * q[1] + rz0 * q[2]; - b = lerpf(u, v, t); - - c = lerpf(a, b, sy); - - q = g3[b00 + bz1]; u = rx0 * q[0] + ry0 * q[1] + rz1 * q[2]; - q = g3[b10 + bz1]; v = rx1 * q[0] + ry0 * q[1] + rz1 * q[2]; - a = lerpf(u, v, t); - - q = g3[b01 + bz1]; u = rx0 * q[0] + ry1 * q[1] + rz1 * q[2]; - q = g3[b11 + bz1]; v = rx1 * q[0] + ry1 * q[1] + rz1 * q[2]; - b = lerpf(u, v, t); - - d = lerpf(a, b, sy); - - return 1.5f*lerpf(c, d, sz); -} - -float SC_turbulencef2(float x, float y, float octaves) -{ - srand(time(NULL)); - float t = 0.0f; - - for (float f = 1.0f; f <= octaves; f *= 2) - t += fabs(SC_noisef2(f * x, f * y)) / f; - return t; -} - -float SC_turbulencef3(float x, float y, float z, float octaves) -{ - srand(time(NULL)); - float t = 0.0f; - - for (float f = 1.0f; f <= octaves; f *= 2) - t += fabs(SC_noisef3(f * x, f * y, f * z)) / f; - return t; -} - -} -} diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp index 677413e..aec2f67 100644 --- a/libs/rs/rsObjectBase.cpp +++ b/libs/rs/rsObjectBase.cpp @@ -15,120 +15,156 @@ */ #include "rsObjectBase.h" + +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif + using namespace android; using namespace android::renderscript; -ObjectBase::ObjectBase(Context *rsc) -{ +pthread_mutex_t ObjectBase::gObjectInitMutex = PTHREAD_MUTEX_INITIALIZER; + +ObjectBase::ObjectBase(Context *rsc) { mUserRefCount = 0; mSysRefCount = 0; - mName = NULL; - mRSC = NULL; + mRSC = rsc; mNext = NULL; mPrev = NULL; - mAllocFile = __FILE__; - mAllocLine = __LINE__; - setContext(rsc); + +#if RS_OBJECT_DEBUG + mStack.update(2); +#endif + + rsAssert(rsc); + add(); + //LOGV("ObjectBase %p con", this); } -ObjectBase::~ObjectBase() -{ +ObjectBase::~ObjectBase() { //LOGV("~ObjectBase %p ref %i,%i", this, mUserRefCount, mSysRefCount); +#if RS_OBJECT_DEBUG + mStack.dump(); +#endif + + if (mPrev || mNext) { + // While the normal practice is to call remove before we call + // delete. Its possible for objects without a re-use list + // for avoiding duplication to be created on the stack. In those + // cases we need to remove ourself here. + asyncLock(); + remove(); + asyncUnlock(); + } + rsAssert(!mUserRefCount); rsAssert(!mSysRefCount); - remove(); - delete[] mName; } -void ObjectBase::dumpLOGV(const char *op) const -{ - if (mName) { - LOGV("%s RSobj %p, name %s, refs %i,%i from %s,%i links %p,%p,%p", - op, this, mName, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC); +void ObjectBase::dumpLOGV(const char *op) const { + if (mName.size()) { + LOGV("%s RSobj %p, name %s, refs %i,%i links %p,%p,%p", + op, this, mName.string(), mUserRefCount, mSysRefCount, mNext, mPrev, mRSC); } else { - LOGV("%s RSobj %p, no-name, refs %i,%i from %s,%i links %p,%p,%p", - op, this, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC); + LOGV("%s RSobj %p, no-name, refs %i,%i links %p,%p,%p", + op, this, mUserRefCount, mSysRefCount, mNext, mPrev, mRSC); } } -void ObjectBase::setContext(Context *rsc) -{ - if (mRSC) { - remove(); - } - mRSC = rsc; - if (rsc) { - add(); - } +void ObjectBase::incUserRef() const { + android_atomic_inc(&mUserRefCount); + //LOGV("ObjectBase %p incU ref %i, %i", this, mUserRefCount, mSysRefCount); } -void ObjectBase::incUserRef() const -{ - mUserRefCount ++; - //LOGV("ObjectBase %p inc ref %i", this, mRefCount); +void ObjectBase::incSysRef() const { + android_atomic_inc(&mSysRefCount); + //LOGV("ObjectBase %p incS ref %i, %i", this, mUserRefCount, mSysRefCount); } -void ObjectBase::incSysRef() const -{ - mSysRefCount ++; - //LOGV("ObjectBase %p inc ref %i", this, mRefCount); +void ObjectBase::preDestroy() const { } -bool ObjectBase::checkDelete() const -{ - if (!(mSysRefCount | mUserRefCount)) { - if (mRSC && mRSC->props.mLogObjects) { - dumpLOGV("checkDelete"); - } - delete this; - return true; +bool ObjectBase::checkDelete(const ObjectBase *ref) { + if (!ref) { + return false; } - return false; + + asyncLock(); + // This lock protects us against the non-RS threads changing + // the ref counts. At this point we should be the only thread + // working on them. + if (ref->mUserRefCount || ref->mSysRefCount) { + asyncUnlock(); + return false; + } + + ref->remove(); + // At this point we can unlock because there should be no possible way + // for another thread to reference this object. + ref->preDestroy(); + asyncUnlock(); + delete ref; + return true; } -bool ObjectBase::decUserRef() const -{ +bool ObjectBase::decUserRef() const { rsAssert(mUserRefCount > 0); - mUserRefCount --; - //dumpObj("decUserRef"); - return checkDelete(); +#if RS_OBJECT_DEBUG + LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount); + if (mUserRefCount <= 0) { + mStack.dump(); + } +#endif + + + if ((android_atomic_dec(&mUserRefCount) <= 1) && + (android_atomic_acquire_load(&mSysRefCount) <= 0)) { + return checkDelete(this); + } + return false; } -bool ObjectBase::zeroUserRef() const -{ - mUserRefCount = 0; - //dumpObj("zeroUserRef"); - return checkDelete(); +bool ObjectBase::zeroUserRef() const { + //LOGV("ObjectBase %p zeroU ref %i, %i", this, mUserRefCount, mSysRefCount); + android_atomic_acquire_store(0, &mUserRefCount); + if (android_atomic_acquire_load(&mSysRefCount) <= 0) { + return checkDelete(this); + } + return false; } -bool ObjectBase::decSysRef() const -{ +bool ObjectBase::decSysRef() const { + //LOGV("ObjectBase %p decS ref %i, %i", this, mUserRefCount, mSysRefCount); rsAssert(mSysRefCount > 0); - mSysRefCount --; - //dumpObj("decSysRef"); - return checkDelete(); + if ((android_atomic_dec(&mSysRefCount) <= 1) && + (android_atomic_acquire_load(&mUserRefCount) <= 0)) { + return checkDelete(this); + } + return false; } -void ObjectBase::setName(const char *name) -{ - setName(name, strlen(name)); +void ObjectBase::setName(const char *name) { + mName.setTo(name); } -void ObjectBase::setName(const char *name, uint32_t len) -{ - delete mName; - mName = NULL; - if (name) { - mName = new char[len + 1]; - memcpy(mName, name, len); - mName[len] = 0; - } +void ObjectBase::setName(const char *name, uint32_t len) { + mName.setTo(name, len); +} + +void ObjectBase::asyncLock() { + pthread_mutex_lock(&gObjectInitMutex); +} + +void ObjectBase::asyncUnlock() { + pthread_mutex_unlock(&gObjectInitMutex); } -void ObjectBase::add() const -{ +void ObjectBase::add() const { + asyncLock(); + rsAssert(!mNext); rsAssert(!mPrev); //LOGV("calling add rsc %p", mRSC); @@ -137,16 +173,18 @@ void ObjectBase::add() const mRSC->mObjHead->mPrev = this; } mRSC->mObjHead = this; + + asyncUnlock(); } -void ObjectBase::remove() const -{ +void ObjectBase::remove() const { //LOGV("calling remove rsc %p", mRSC); if (!mRSC) { rsAssert(!mPrev); rsAssert(!mNext); return; } + if (mRSC->mObjHead == this) { mRSC->mObjHead = mNext; } @@ -160,8 +198,7 @@ void ObjectBase::remove() const mNext = NULL; } -void ObjectBase::zeroAllUserRef(Context *rsc) -{ +void ObjectBase::zeroAllUserRef(Context *rsc) { if (rsc->props.mLogObjects) { LOGV("Forcing release of all outstanding user refs."); } @@ -186,8 +223,9 @@ void ObjectBase::zeroAllUserRef(Context *rsc) } } -void ObjectBase::dumpAll(Context *rsc) -{ +void ObjectBase::dumpAll(Context *rsc) { + asyncLock(); + LOGV("Dumping all objects"); const ObjectBase * o = rsc->mObjHead; while (o) { @@ -195,5 +233,22 @@ void ObjectBase::dumpAll(Context *rsc) o->dumpLOGV(" "); o = o->mNext; } + + asyncUnlock(); +} + +bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj) { + asyncLock(); + + const ObjectBase * o = rsc->mObjHead; + while (o) { + if (o == obj) { + asyncUnlock(); + return true; + } + o = o->mNext; + } + asyncUnlock(); + return false; } diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h index bb03b87..01850f1 100644 --- a/libs/rs/rsObjectBase.h +++ b/libs/rs/rsObjectBase.h @@ -19,18 +19,20 @@ #include "rsUtils.h" +#define RS_OBJECT_DEBUG 0 + +#include <utils/CallStack.h> namespace android { namespace renderscript { class Context; +class OStream; // An element is a group of Components that occupies one cell in a structure. -class ObjectBase -{ +class ObjectBase { public: ObjectBase(Context *rsc); - virtual ~ObjectBase(); void incSysRef() const; bool decSysRef() const; @@ -39,42 +41,59 @@ public: bool decUserRef() const; bool zeroUserRef() const; + static bool checkDelete(const ObjectBase *); + const char * getName() const { - return mName; + return mName.string(); } void setName(const char *); void setName(const char *, uint32_t len); Context * getContext() const {return mRSC;} - void setContext(Context *); static void zeroAllUserRef(Context *rsc); static void dumpAll(Context *rsc); virtual void dumpLOGV(const char *prefix) const; + virtual void serialize(OStream *stream) const = 0; + virtual RsA3DClassID getClassId() const = 0; + + static bool isValid(const Context *rsc, const ObjectBase *obj); + + // The async lock is taken during object creation in non-rs threads + // and object deletion in the rs thread. + static void asyncLock(); + static void asyncUnlock(); protected: - const char *mAllocFile; - uint32_t mAllocLine; + // Called inside the async lock for any object list management that is + // necessary in derived classes. + virtual void preDestroy() const; + Context *mRSC; + virtual ~ObjectBase(); private: + static pthread_mutex_t gObjectInitMutex; + void add() const; void remove() const; - bool checkDelete() const; - - char * mName; + String8 mName; mutable int32_t mSysRefCount; mutable int32_t mUserRefCount; mutable const ObjectBase * mPrev; mutable const ObjectBase * mNext; + +#if RS_OBJECT_DEBUG + CallStack mStack; +#endif + }; template<class T> -class ObjectBaseRef -{ +class ObjectBaseRef { public: ObjectBaseRef() { mRef = NULL; @@ -94,6 +113,10 @@ public: } } + ObjectBaseRef & operator= (const ObjectBaseRef &ref) { + return ObjectBaseRef(ref); + } + ~ObjectBaseRef() { clear(); } @@ -129,10 +152,8 @@ public: protected: T * mRef; - }; - } } diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp index 70e2868..39b85e3 100644 --- a/libs/rs/rsProgram.cpp +++ b/libs/rs/rsProgram.cpp @@ -14,50 +14,30 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" -#include "rsProgram.h" - #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> +#endif //ANDROID_RS_BUILD_FOR_HOST + +#include "rsProgram.h" using namespace android; using namespace android::renderscript; - -Program::Program(Context *rsc) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; - mDirty = true; - mShaderID = 0; - mAttribCount = 0; - mUniformCount = 0; - - mInputElements = NULL; - mOutputElements = NULL; - mConstantTypes = NULL; - mInputCount = 0; - mOutputCount = 0; - mConstantCount = 0; - mIsValid = false; +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) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; - mDirty = true; - mShaderID = 0; - mAttribCount = 0; - mUniformCount = 0; - mTextureCount = 0; - - mInputCount = 0; - mOutputCount = 0; - mConstantCount = 0; + const uint32_t * params, uint32_t paramLength) + : ObjectBase(rsc) { + initMemberVars(); for (uint32_t ct=0; ct < paramLength; ct+=2) { if (params[ct] == RS_PROGRAM_PARAM_INPUT) { mInputCount++; @@ -68,18 +48,23 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength, if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) { mConstantCount++; } - if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) { - mTextureCount = params[ct+1]; + if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) { + mTextureCount++; } } + 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]; 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])); @@ -90,27 +75,94 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength, if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) { mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1])); } + if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) { + mTextureTargets[texture++] = (RsTextureTarget)params[ct+1]; + } + } + mIsInternal = false; + uint32_t internalTokenLen = strlen(RS_SHADER_INTERNAL); + if (shaderLength > internalTokenLen && + strncmp(RS_SHADER_INTERNAL, shaderText, internalTokenLen) == 0) { + mIsInternal = true; + shaderText += internalTokenLen; + shaderLength -= internalTokenLen; } mUserShader.setTo(shaderText, shaderLength); + + initAttribAndUniformArray(); } -Program::~Program() -{ - for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) { - bindAllocation(NULL, ct); +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++) { + bindAllocation(NULL, NULL, ct); + } + + for (uint32_t ct=0; ct < mTextureCount; 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; } +void Program::initMemberVars() { + mDirty = true; + mShaderID = 0; + mAttribCount = 0; + mUniformCount = 0; + mTextureCount = 0; -void Program::bindAllocation(Allocation *alloc, uint32_t slot) -{ + 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; + mIsInternal = false; +} + +void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) { + if (alloc != NULL) { + if (slot >= mConstantCount) { + LOGE("Attempt to bind alloc at slot %u, on shader id %u, but const count is %u", + slot, (uint32_t)this, mConstantCount); + rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation"); + return; + } + if (!alloc->getType()->isEqual(mConstantTypes[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) { return; } @@ -124,10 +176,16 @@ void Program::bindAllocation(Allocation *alloc, uint32_t slot) mDirty = true; } -void Program::bindTexture(uint32_t slot, Allocation *a) -{ - if (slot >= MAX_TEXTURE) { - LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE"); +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); + rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind texture"); + return; + } + + if (a && a->getType()->getDimFaces() && mTextureTargets[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; } @@ -136,10 +194,10 @@ void Program::bindTexture(uint32_t slot, Allocation *a) mDirty = true; } -void Program::bindSampler(uint32_t slot, Sampler *s) -{ - if (slot >= MAX_TEXTURE) { - LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE"); +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); + rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind sampler"); return; } @@ -147,8 +205,7 @@ void Program::bindSampler(uint32_t slot, Sampler *s) mDirty = true; } -String8 Program::getGLSLInputString() const -{ +String8 Program::getGLSLInputString() const { String8 s; for (uint32_t ct=0; ct < mInputCount; ct++) { const Element *e = mInputElements[ct].get(); @@ -157,7 +214,7 @@ String8 Program::getGLSLInputString() const // Cannot be complex rsAssert(!f->getFieldCount()); - switch(f->getComponent().getVectorSize()) { + 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; @@ -173,23 +230,18 @@ String8 Program::getGLSLInputString() const return s; } -String8 Program::getGLSLOutputString() const -{ +String8 Program::getGLSLOutputString() const { return String8(); } -String8 Program::getGLSLConstantString() const -{ +String8 Program::getGLSLConstantString() const { return String8(); } - -void Program::createShader() -{ +void Program::createShader() { } -bool Program::loadShader(Context *rsc, uint32_t type) -{ +bool Program::loadShader(Context *rsc, uint32_t type) { mShaderID = glCreateShader(type); rsAssert(mShaderID); @@ -230,33 +282,238 @@ bool Program::loadShader(Context *rsc, uint32_t type) return true; } -void Program::setShader(const char *txt, uint32_t len) -{ +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 { - -void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants) -{ +void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants) { Program *p = static_cast<Program *>(vp); - p->bindAllocation(static_cast<Allocation *>(constants), slot); + p->bindAllocation(rsc, static_cast<Allocation *>(constants), slot); } -void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a) -{ +void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a) { Program *p = static_cast<Program *>(vpf); - p->bindTexture(slot, static_cast<Allocation *>(a)); + p->bindTexture(rsc, slot, static_cast<Allocation *>(a)); } -void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s) -{ +void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s) { Program *p = static_cast<Program *>(vpf); - p->bindSampler(slot, static_cast<Sampler *>(s)); + p->bindSampler(rsc, slot, static_cast<Sampler *>(s)); } } diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h index 86f85fb..c48464d 100644 --- a/libs/rs/rsProgram.h +++ b/libs/rs/rsProgram.h @@ -23,29 +23,27 @@ // --------------------------------------------------------------------------- namespace android { namespace renderscript { - - class ShaderCache; -class Program : public ObjectBase -{ +#define RS_SHADER_INTERNAL "//rs_shader_internal\n" +#define RS_SHADER_ATTR "ATTRIB_" +#define RS_SHADER_UNI "UNI_" + +class Program : public ObjectBase { public: - const static uint32_t MAX_ATTRIBS = 8; - const static uint32_t MAX_UNIFORMS = 16; - const static uint32_t MAX_TEXTURE = 2; Program(Context *); Program(Context *, const char * shaderText, uint32_t shaderLength, const uint32_t * params, uint32_t paramLength); virtual ~Program(); - void bindAllocation(Allocation *, uint32_t slot); + void bindAllocation(Context *, Allocation *, uint32_t slot); virtual void createShader(); - bool isUserProgram() const {return mUserShader.size() > 0;} + bool isUserProgram() const {return !mIsInternal;} - void bindTexture(uint32_t slot, Allocation *); - void bindSampler(uint32_t slot, Sampler *); + 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); @@ -54,12 +52,14 @@ public: 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;} protected: // Components not listed in "in" will be passed though @@ -67,12 +67,19 @@ protected: 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); - ObjectBaseRef<Allocation> mConstants[MAX_UNIFORMS]; + void initAttribAndUniformArray(); mutable bool mDirty; String8 mShader; @@ -82,8 +89,13 @@ protected: uint32_t mTextureCount; uint32_t mAttribCount; uint32_t mUniformCount; - String8 mAttribNames[MAX_ATTRIBS]; - String8 mUniformNames[MAX_UNIFORMS]; + 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 @@ -91,17 +103,12 @@ protected: // and filtered. // // Constants are strictly accessed by programetic loads. - ObjectBaseRef<Allocation> mTextures[MAX_TEXTURE]; - ObjectBaseRef<Sampler> mSamplers[MAX_TEXTURE]; - + ObjectBaseRef<Allocation> *mTextures; + ObjectBaseRef<Sampler> *mSamplers; + RsTextureTarget *mTextureTargets; bool loadShader(Context *, uint32_t type); - -public: - void forceDirty() const {mDirty = true;} }; - - } } #endif diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp index c17b94c..22cd5d3 100644 --- a/libs/rs/rsProgramFragment.cpp +++ b/libs/rs/rsProgramFragment.cpp @@ -14,161 +14,109 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" -#include "rsProgramFragment.h" - #include <GLES/gl.h> #include <GLES/glext.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> +#endif //ANDROID_RS_BUILD_FOR_HOST + +#include "rsProgramFragment.h" using namespace android; using namespace android::renderscript; - -ProgramFragment::ProgramFragment(Context *rsc, const uint32_t * params, - uint32_t paramLength) : - Program(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; - rsAssert(paramLength = 5); - - mEnvModes[0] = (RsTexEnvMode)params[0]; - mTextureFormats[0] = params[1]; - mEnvModes[1] = (RsTexEnvMode)params[2]; - mTextureFormats[1] = params[3]; - mPointSpriteEnable = params[4] != 0; - - mTextureEnableMask = 0; - if (mEnvModes[0]) { - mTextureEnableMask |= 1; - } - if (mEnvModes[1]) { - mTextureEnableMask |= 2; - } - init(rsc); -} - ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText, uint32_t shaderLength, const uint32_t * params, - uint32_t paramLength) : - Program(rsc, shaderText, shaderLength, params, paramLength) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; + 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); - mTextureEnableMask = (1 << mTextureCount) -1; } - -ProgramFragment::~ProgramFragment() -{ +ProgramFragment::~ProgramFragment() { + if (mShaderID) { + mRSC->mShaderCache.cleanupFragment(mShaderID); + } } -void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state) -{ - if ((state->mLast.get() == this) && !mDirty) { +void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b, float a) { + if (isUserProgram()) { + LOGE("Attempting to set fixed function emulation color on user program"); + rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set fixed function emulation color on user program"); return; } - state->mLast.set(this); - - for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) { - glActiveTexture(GL_TEXTURE0 + ct); - if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) { - glDisable(GL_TEXTURE_2D); - continue; - } - - glEnable(GL_TEXTURE_2D); - if (rsc->checkVersion1_1()) { - if (mPointSpriteEnable) { - glEnable(GL_POINT_SPRITE_OES); - } else { - glDisable(GL_POINT_SPRITE_OES); - } - glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable); - } - mTextures[ct]->uploadCheck(rsc); - glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID()); - - switch(mEnvModes[ct]) { - case RS_TEX_ENV_MODE_NONE: - rsAssert(0); - break; - case RS_TEX_ENV_MODE_REPLACE: - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - break; - case RS_TEX_ENV_MODE_MODULATE: - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - break; - case RS_TEX_ENV_MODE_DECAL: - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); - break; - } - - if (mSamplers[ct].get()) { - mSamplers[ct]->setupGL(rsc, mTextures[ct]->getType()->getIsNp2()); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - - // Gross hack. - if (ct == 2) { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); - } + if (mConstants[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; } - glActiveTexture(GL_TEXTURE0); - mDirty = false; - rsc->checkError("ProgramFragment::setupGL"); + mConstantColor[0] = r; + mConstantColor[1] = g; + mConstantColor[2] = b; + mConstantColor[3] = a; + memcpy(mConstants[0]->getPtr(), mConstantColor, 4*sizeof(float)); + mDirty = true; } -void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc) -{ - +void ProgramFragment::setupGL2(Context *rsc, ProgramFragmentState *state, ShaderCache *sc) { //LOGE("sgl2 frag1 %x", glGetError()); if ((state->mLast.get() == this) && !mDirty) { - //return; + return; } state->mLast.set(this); rsc->checkError("ProgramFragment::setupGL2 start"); - for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) { + + 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 (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) { + if (!mTextures[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); - glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID()); + 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]->getType()->getIsNp2()); + mSamplers[ct]->setupGL(rsc, mTextures[ct].get()); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + 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(ct), ct); + glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct); rsc->checkError("ProgramFragment::setupGL2 uniforms"); } @@ -181,162 +129,104 @@ void ProgramFragment::loadShader(Context *rsc) { Program::loadShader(rsc, GL_FRAGMENT_SHADER); } -void ProgramFragment::createShader() -{ - mShader.setTo("precision mediump float;\n"); - mShader.append("varying vec4 varColor;\n"); - mShader.append("varying vec4 varTex0;\n"); - +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++) { - char buf[256]; - sprintf(buf, "uniform sampler2D uni_Tex%i;\n", 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 { - uint32_t mask = mTextureEnableMask; - uint32_t texNum = 0; - while (mask) { - if (mask & 1) { - char buf[64]; - mShader.append("uniform sampler2D uni_Tex"); - sprintf(buf, "%i", texNum); - mShader.append(buf); - mShader.append(";\n"); - } - mask >>= 1; - texNum++; - } - - - mShader.append("void main() {\n"); - mShader.append(" vec4 col = varColor;\n"); - - if (mTextureEnableMask) { - if (mPointSpriteEnable) { - mShader.append(" vec2 t0 = gl_PointCoord;\n"); - } else { - mShader.append(" vec2 t0 = varTex0.xy;\n"); - } - } - - mask = mTextureEnableMask; - texNum = 0; - while (mask) { - if (mask & 1) { - switch(mEnvModes[texNum]) { - case RS_TEX_ENV_MODE_NONE: - rsAssert(0); - break; - case RS_TEX_ENV_MODE_REPLACE: - switch(mTextureFormats[texNum]) { - case 1: - mShader.append(" col.a = texture2D(uni_Tex0, t0).a;\n"); - break; - case 2: - mShader.append(" col.rgba = texture2D(uni_Tex0, t0).rgba;\n"); - break; - case 3: - mShader.append(" col.rgb = texture2D(uni_Tex0, t0).rgb;\n"); - break; - case 4: - mShader.append(" col.rgba = texture2D(uni_Tex0, t0).rgba;\n"); - break; - } - break; - case RS_TEX_ENV_MODE_MODULATE: - switch(mTextureFormats[texNum]) { - case 1: - mShader.append(" col.a *= texture2D(uni_Tex0, t0).a;\n"); - break; - case 2: - mShader.append(" col.rgba *= texture2D(uni_Tex0, t0).rgba;\n"); - break; - case 3: - mShader.append(" col.rgb *= texture2D(uni_Tex0, t0).rgb;\n"); - break; - case 4: - mShader.append(" col.rgba *= texture2D(uni_Tex0, t0).rgba;\n"); - break; - } - break; - case RS_TEX_ENV_MODE_DECAL: - mShader.append(" col = texture2D(uni_Tex0, t0);\n"); - break; - } + LOGE("ProgramFragment::createShader cannot create program, shader code not defined"); + rsAssert(0); + } +} - } - mask >>= 1; - texNum++; +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++; + } - //mShader.append(" col.a = 1.0;\n"); - //mShader.append(" col.r = 0.5;\n"); + createShader(); +} - mShader.append(" gl_FragColor = col;\n"); - mShader.append("}\n"); - } +void ProgramFragment::serialize(OStream *stream) const { } -void ProgramFragment::init(Context *rsc) -{ - mUniformCount = 2; - mUniformNames[0].setTo("uni_Tex0"); - mUniformNames[1].setTo("uni_Tex1"); +ProgramFragment *ProgramFragment::createFromStream(Context *rsc, IStream *stream) { + return NULL; +} - createShader(); +ProgramFragmentState::ProgramFragmentState() { + mPF = NULL; } -ProgramFragmentState::ProgramFragmentState() -{ +ProgramFragmentState::~ProgramFragmentState() { + ObjectBase::checkDelete(mPF); mPF = NULL; } -ProgramFragmentState::~ProgramFragmentState() -{ - delete mPF; +void ProgramFragmentState::init(Context *rsc) { + String8 shaderString(RS_SHADER_INTERNAL); + shaderString.append("varying lowp vec4 varColor;\n"); + shaderString.append("varying vec2 varTex0;\n"); + shaderString.append("void main() {\n"); + shaderString.append(" lowp vec4 col = UNI_Color;\n"); + shaderString.append(" gl_FragColor = col;\n"); + shaderString.append("}\n"); -} + const Element *colorElem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); + rsc->mStateElement.elementBuilderBegin(); + rsc->mStateElement.elementBuilderAdd(colorElem, "Color", 1); + const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc); + + Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false); + + uint32_t tmp[2]; + 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); + ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(), + shaderString.length(), tmp, 2); + pf->bindAllocation(rsc, constAlloc, 0); + pf->setConstantColor(rsc, 1.0f, 1.0f, 1.0f, 1.0f); -void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h) -{ - uint32_t tmp[5] = { - RS_TEX_ENV_MODE_NONE, 0, - RS_TEX_ENV_MODE_NONE, 0, - 0 - }; - ProgramFragment *pf = new ProgramFragment(rsc, tmp, 5); mDefault.set(pf); - pf->init(rsc); } -void ProgramFragmentState::deinit(Context *rsc) -{ +void ProgramFragmentState::deinit(Context *rsc) { mDefault.clear(); mLast.clear(); } - namespace android { namespace renderscript { -RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc, - const uint32_t * params, - uint32_t paramLength) -{ - ProgramFragment *pf = new ProgramFragment(rsc, params, paramLength); - pf->incUserRef(); - return pf; -} - -RsProgramFragment rsi_ProgramFragmentCreate2(Context *rsc, const char * shaderText, +RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc, const char * shaderText, uint32_t shaderLength, const uint32_t * params, - uint32_t paramLength) -{ + uint32_t paramLength) { ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength); pf->incUserRef(); + //LOGE("rsi_ProgramFragmentCreate %p", pf); return pf; } diff --git a/libs/rs/rsProgramFragment.h b/libs/rs/rsProgramFragment.h index 9fa565d..3d28946 100644 --- a/libs/rs/rsProgramFragment.h +++ b/libs/rs/rsProgramFragment.h @@ -25,49 +25,44 @@ namespace renderscript { class ProgramFragmentState; -class ProgramFragment : public Program -{ +class ProgramFragment : public Program { public: - ProgramFragment(Context *, const uint32_t * params, uint32_t paramLength); ProgramFragment(Context *rsc, const char * shaderText, uint32_t shaderLength, const uint32_t * params, uint32_t paramLength); virtual ~ProgramFragment(); - virtual void setupGL(const Context *, ProgramFragmentState *); - virtual void setupGL2(const Context *, ProgramFragmentState *, ShaderCache *sc); + virtual void setupGL2(Context *, ProgramFragmentState *, ShaderCache *sc); 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); + + void setConstantColor(Context *, float, float, float, float); protected: - // Hacks to create a program for now - uint32_t mTextureFormats[MAX_TEXTURE]; - uint32_t mTextureDimensions[MAX_TEXTURE]; - RsTexEnvMode mEnvModes[MAX_TEXTURE]; - uint32_t mTextureEnableMask; - bool mPointSpriteEnable; + float mConstantColor[4]; + int32_t mTextureUniformIndexStart; }; -class ProgramFragmentState -{ +class ProgramFragmentState { public: ProgramFragmentState(); ~ProgramFragmentState(); ProgramFragment *mPF; - void init(Context *rsc, int32_t w, int32_t h); + void init(Context *rsc); void deinit(Context *rsc); - ObjectBaseRef<Type> mTextureTypes[ProgramFragment::MAX_TEXTURE]; ObjectBaseRef<ProgramFragment> mDefault; Vector<ProgramFragment *> mPrograms; ObjectBaseRef<ProgramFragment> mLast; }; - } } #endif diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp index 13887d1..f2b5b9a 100644 --- a/libs/rs/rsProgramRaster.cpp +++ b/libs/rs/rsProgramRaster.cpp @@ -14,136 +14,118 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" -#include "rsProgramRaster.h" - #include <GLES/gl.h> #include <GLES/glext.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#include <OpenGl/glext.h> +#endif //ANDROID_RS_BUILD_FOR_HOST + +#include "rsProgramRaster.h" using namespace android; using namespace android::renderscript; -ProgramRaster::ProgramRaster(Context *rsc, - bool pointSmooth, - bool lineSmooth, - bool pointSprite) : - Program(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +ProgramRaster::ProgramRaster(Context *rsc, bool pointSmooth, + bool lineSmooth, bool pointSprite) + : Program(rsc) { + mPointSmooth = pointSmooth; mLineSmooth = lineSmooth; mPointSprite = pointSprite; - - mPointSize = 1.0f; mLineWidth = 1.0f; + mCull = RS_CULL_BACK; } -ProgramRaster::~ProgramRaster() -{ +ProgramRaster::~ProgramRaster() { } -void ProgramRaster::setLineWidth(float s) -{ +void ProgramRaster::setLineWidth(float s) { mLineWidth = s; + mDirty = true; } -void ProgramRaster::setPointSize(float s) -{ - mPointSize = s; +void ProgramRaster::setCullMode(RsCullMode mode) { + mCull = mode; + mDirty = true; } -void ProgramRaster::setupGL(const Context *rsc, ProgramRasterState *state) -{ - if (state->mLast.get() == this) { +void ProgramRaster::setupGL2(const Context *rsc, ProgramRasterState *state) { + if (state->mLast.get() == this && !mDirty) { return; } state->mLast.set(this); - - glPointSize(mPointSize); - if (mPointSmooth) { - glEnable(GL_POINT_SMOOTH); - } else { - glDisable(GL_POINT_SMOOTH); - } - - glLineWidth(mLineWidth); - if (mLineSmooth) { - glEnable(GL_LINE_SMOOTH); - } else { - glDisable(GL_LINE_SMOOTH); - } - - if (rsc->checkVersion1_1()) { - if (mPointSprite) { - glEnable(GL_POINT_SPRITE_OES); - } else { - glDisable(GL_POINT_SPRITE_OES); - } + 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; } } -void ProgramRaster::setupGL2(const Context *rsc, ProgramRasterState *state) -{ - if (state->mLast.get() == this) { - return; - } - state->mLast.set(this); +void ProgramRaster::serialize(OStream *stream) const { } +ProgramRaster *ProgramRaster::createFromStream(Context *rsc, IStream *stream) { + return NULL; +} - -ProgramRasterState::ProgramRasterState() -{ +ProgramRasterState::ProgramRasterState() { } -ProgramRasterState::~ProgramRasterState() -{ +ProgramRasterState::~ProgramRasterState() { } -void ProgramRasterState::init(Context *rsc, int32_t w, int32_t h) -{ +void ProgramRasterState::init(Context *rsc) { ProgramRaster *pr = new ProgramRaster(rsc, false, false, false); mDefault.set(pr); } -void ProgramRasterState::deinit(Context *rsc) -{ +void ProgramRasterState::deinit(Context *rsc) { mDefault.clear(); mLast.clear(); } - namespace android { namespace renderscript { -RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, RsElement in, RsElement out, +RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, bool pointSmooth, bool lineSmooth, - bool pointSprite) -{ - ProgramRaster *pr = new ProgramRaster(rsc, - pointSmooth, - lineSmooth, - pointSprite); + bool pointSprite) { + ProgramRaster *pr = new ProgramRaster(rsc, pointSmooth, + lineSmooth, pointSprite); pr->incUserRef(); return pr; } -void rsi_ProgramRasterSetPointSize(Context * rsc, RsProgramRaster vpr, float s) -{ +void rsi_ProgramRasterSetLineWidth(Context * rsc, + RsProgramRaster vpr, + float s) { ProgramRaster *pr = static_cast<ProgramRaster *>(vpr); - pr->setPointSize(s); + pr->setLineWidth(s); } -void rsi_ProgramRasterSetLineWidth(Context * rsc, RsProgramRaster vpr, float s) -{ +void rsi_ProgramRasterSetCullMode(Context * rsc, + RsProgramRaster vpr, + RsCullMode mode) { ProgramRaster *pr = static_cast<ProgramRaster *>(vpr); - pr->setLineWidth(s); + pr->setCullMode(mode); } - } } diff --git a/libs/rs/rsProgramRaster.h b/libs/rs/rsProgramRaster.h index c3a9c90..7958af9 100644 --- a/libs/rs/rsProgramRaster.h +++ b/libs/rs/rsProgramRaster.h @@ -25,8 +25,7 @@ namespace renderscript { class ProgramRasterState; -class ProgramRaster : public Program -{ +class ProgramRaster : public Program { public: ProgramRaster(Context *rsc, bool pointSmooth, @@ -34,29 +33,27 @@ public: bool pointSprite); virtual ~ProgramRaster(); - virtual void setupGL(const Context *, ProgramRasterState *); virtual void setupGL2(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 setPointSize(float s); + void setCullMode(RsCullMode mode); protected: bool mPointSmooth; bool mLineSmooth; bool mPointSprite; - - float mPointSize; float mLineWidth; - - + RsCullMode mCull; }; -class ProgramRasterState -{ +class ProgramRasterState { public: ProgramRasterState(); ~ProgramRasterState(); - void init(Context *rsc, int32_t w, int32_t h); + void init(Context *rsc); void deinit(Context *rsc); ObjectBaseRef<ProgramRaster> mDefault; diff --git a/libs/rs/rsProgramFragmentStore.cpp b/libs/rs/rsProgramStore.cpp index 8a2157f..72ac574 100644 --- a/libs/rs/rsProgramFragmentStore.cpp +++ b/libs/rs/rsProgramStore.cpp @@ -14,21 +14,23 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" -#include "rsProgramFragmentStore.h" - #include <GLES/gl.h> #include <GLES/glext.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#include <OpenGl/glext.h> +#endif //ANDROID_RS_BUILD_FOR_HOST + +#include "rsProgramStore.h" using namespace android; using namespace android::renderscript; -ProgramFragmentStore::ProgramFragmentStore(Context *rsc) : - Program(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +ProgramStore::ProgramStore(Context *rsc) : Program(rsc) { mDitherEnable = true; mBlendEnable = false; mColorRWriteEnable = true; @@ -38,20 +40,15 @@ ProgramFragmentStore::ProgramFragmentStore(Context *rsc) : mBlendSrc = GL_ONE; mBlendDst = GL_ZERO; - mDepthTestEnable = false; mDepthWriteEnable = true; mDepthFunc = GL_LESS; - - } -ProgramFragmentStore::~ProgramFragmentStore() -{ +ProgramStore::~ProgramStore() { } -void ProgramFragmentStore::setupGL(const Context *rsc, ProgramFragmentStoreState *state) -{ +void ProgramStore::setupGL2(const Context *rsc, ProgramStoreState *state) { if (state->mLast.get() == this) { return; } @@ -70,47 +67,23 @@ void ProgramFragmentStore::setupGL(const Context *rsc, ProgramFragmentStoreState //LOGE("pfs %i, %i, %x", mDepthWriteEnable, mDepthTestEnable, mDepthFunc); - glDepthMask(mDepthWriteEnable); - if(mDepthTestEnable || mDepthWriteEnable) { - glEnable(GL_DEPTH_TEST); - glDepthFunc(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 (mDitherEnable) { - glEnable(GL_DITHER); - } else { - glDisable(GL_DITHER); - } -} - -void ProgramFragmentStore::setupGL2(const Context *rsc, ProgramFragmentStoreState *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); - - glDepthMask(mDepthWriteEnable); - if(mDepthTestEnable || mDepthWriteEnable) { - glEnable(GL_DEPTH_TEST); - glDepthFunc(mDepthFunc); + if (rsc->mUserSurfaceConfig.stencilMin > 0) { } else { - glDisable(GL_DEPTH_TEST); + glStencilMask(0); + glDisable(GL_STENCIL_TEST); } if (mDitherEnable) { @@ -120,17 +93,21 @@ void ProgramFragmentStore::setupGL2(const Context *rsc, ProgramFragmentStoreStat } } - -void ProgramFragmentStore::setDitherEnable(bool enable) -{ +void ProgramStore::setDitherEnable(bool enable) { mDitherEnable = enable; } -void ProgramFragmentStore::setDepthFunc(RsDepthFunc func) -{ +void ProgramStore::serialize(OStream *stream) const { +} + +ProgramStore *ProgramStore::createFromStream(Context *rsc, IStream *stream) { + return NULL; +} + +void ProgramStore::setDepthFunc(RsDepthFunc func) { mDepthTestEnable = true; - switch(func) { + switch (func) { case RS_DEPTH_FUNC_ALWAYS: mDepthTestEnable = false; mDepthFunc = GL_ALWAYS; @@ -156,20 +133,18 @@ void ProgramFragmentStore::setDepthFunc(RsDepthFunc func) } } -void ProgramFragmentStore::setDepthMask(bool mask) -{ +void ProgramStore::setDepthMask(bool mask) { mDepthWriteEnable = mask; } -void ProgramFragmentStore::setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst) -{ +void ProgramStore::setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst) { mBlendEnable = true; if ((src == RS_BLEND_SRC_ONE) && (dst == RS_BLEND_DST_ZERO)) { mBlendEnable = false; } - switch(src) { + switch (src) { case RS_BLEND_SRC_ZERO: mBlendSrc = GL_ZERO; break; @@ -199,7 +174,7 @@ void ProgramFragmentStore::setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst) break; } - switch(dst) { + switch (dst) { case RS_BLEND_DST_ZERO: mBlendDst = GL_ZERO; break; @@ -227,82 +202,66 @@ void ProgramFragmentStore::setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst) } } -void ProgramFragmentStore::setColorMask(bool r, bool g, bool b, bool a) -{ +void ProgramStore::setColorMask(bool r, bool g, bool b, bool a) { mColorRWriteEnable = r; mColorGWriteEnable = g; mColorBWriteEnable = b; mColorAWriteEnable = a; } - -ProgramFragmentStoreState::ProgramFragmentStoreState() -{ +ProgramStoreState::ProgramStoreState() { mPFS = NULL; } -ProgramFragmentStoreState::~ProgramFragmentStoreState() -{ - delete mPFS; - +ProgramStoreState::~ProgramStoreState() { + ObjectBase::checkDelete(mPFS); + mPFS = NULL; } -void ProgramFragmentStoreState::init(Context *rsc, int32_t w, int32_t h) -{ - ProgramFragmentStore *pfs = new ProgramFragmentStore(rsc); +void ProgramStoreState::init(Context *rsc) { + ProgramStore *pfs = new ProgramStore(rsc); mDefault.set(pfs); } -void ProgramFragmentStoreState::deinit(Context *rsc) -{ +void ProgramStoreState::deinit(Context *rsc) { mDefault.clear(); mLast.clear(); } - namespace android { namespace renderscript { -void rsi_ProgramFragmentStoreBegin(Context * rsc, RsElement in, RsElement out) -{ - delete rsc->mStateFragmentStore.mPFS; - rsc->mStateFragmentStore.mPFS = new ProgramFragmentStore(rsc); - +void rsi_ProgramStoreBegin(Context * rsc, RsElement in, RsElement out) { + ObjectBase::checkDelete(rsc->mStateFragmentStore.mPFS); + rsc->mStateFragmentStore.mPFS = new ProgramStore(rsc); } -void rsi_ProgramFragmentStoreDepthFunc(Context *rsc, RsDepthFunc func) -{ +void rsi_ProgramStoreDepthFunc(Context *rsc, RsDepthFunc func) { rsc->mStateFragmentStore.mPFS->setDepthFunc(func); } -void rsi_ProgramFragmentStoreDepthMask(Context *rsc, bool mask) -{ +void rsi_ProgramStoreDepthMask(Context *rsc, bool mask) { rsc->mStateFragmentStore.mPFS->setDepthMask(mask); } -void rsi_ProgramFragmentStoreColorMask(Context *rsc, bool r, bool g, bool b, bool a) -{ +void rsi_ProgramStoreColorMask(Context *rsc, bool r, bool g, bool b, bool a) { rsc->mStateFragmentStore.mPFS->setColorMask(r, g, b, a); } -void rsi_ProgramFragmentStoreBlendFunc(Context *rsc, RsBlendSrcFunc src, RsBlendDstFunc dst) -{ +void rsi_ProgramStoreBlendFunc(Context *rsc, RsBlendSrcFunc src, RsBlendDstFunc dst) { rsc->mStateFragmentStore.mPFS->setBlendFunc(src, dst); } -RsProgramFragmentStore rsi_ProgramFragmentStoreCreate(Context *rsc) -{ - ProgramFragmentStore *pfs = rsc->mStateFragmentStore.mPFS; +RsProgramStore rsi_ProgramStoreCreate(Context *rsc) { + ProgramStore *pfs = rsc->mStateFragmentStore.mPFS; pfs->incUserRef(); rsc->mStateFragmentStore.mPFS = 0; return pfs; } -void rsi_ProgramFragmentStoreDither(Context *rsc, bool enable) -{ +void rsi_ProgramStoreDither(Context *rsc, bool enable) { rsc->mStateFragmentStore.mPFS->setDitherEnable(enable); } - } } diff --git a/libs/rs/rsProgramFragmentStore.h b/libs/rs/rsProgramStore.h index 3412c99..f8eb7cf 100644 --- a/libs/rs/rsProgramFragmentStore.h +++ b/libs/rs/rsProgramStore.h @@ -18,21 +18,20 @@ #define ANDROID_RS_PROGRAM_FRAGMENT_STORE_H #include "rsProgram.h" +#include "rsStream.h" // --------------------------------------------------------------------------- namespace android { namespace renderscript { -class ProgramFragmentStoreState; +class ProgramStoreState; -class ProgramFragmentStore : public Program -{ +class ProgramStore : public Program { public: - ProgramFragmentStore(Context *); - virtual ~ProgramFragmentStore(); + ProgramStore(Context *); + virtual ~ProgramStore(); - virtual void setupGL(const Context *, ProgramFragmentStoreState *); - virtual void setupGL2(const Context *, ProgramFragmentStoreState *); + virtual void setupGL2(const Context *, ProgramStoreState *); void setDepthFunc(RsDepthFunc); void setDepthMask(bool); @@ -42,6 +41,10 @@ public: void setDitherEnable(bool); + 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; @@ -60,22 +63,20 @@ protected: bool mStencilTestEnable; }; -class ProgramFragmentStoreState -{ +class ProgramStoreState { public: - ProgramFragmentStoreState(); - ~ProgramFragmentStoreState(); - void init(Context *rsc, int32_t w, int32_t h); + ProgramStoreState(); + ~ProgramStoreState(); + void init(Context *rsc); void deinit(Context *rsc); - ObjectBaseRef<ProgramFragmentStore> mDefault; - ObjectBaseRef<ProgramFragmentStore> mLast; + ObjectBaseRef<ProgramStore> mDefault; + ObjectBaseRef<ProgramStore> mLast; - ProgramFragmentStore *mPFS; + ProgramStore *mPFS; }; - } } #endif diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp index a2b2df4..ad2beaf 100644 --- a/libs/rs/rsProgramVertex.cpp +++ b/libs/rs/rsProgramVertex.cpp @@ -14,146 +14,59 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" -#include "rsProgramVertex.h" - #include <GLES/gl.h> #include <GLES/glext.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> +#endif //ANDROID_RS_BUILD_FOR_HOST + +#include "rsProgramVertex.h" using namespace android; using namespace android::renderscript; -ProgramVertex::ProgramVertex(Context *rsc, bool texMat) : - Program(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; - mTextureMatrixEnable = texMat; - mLightCount = 0; - init(rsc); -} - ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText, uint32_t shaderLength, const uint32_t * params, - uint32_t paramLength) : - Program(rsc, shaderText, shaderLength, params, paramLength) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; - mTextureMatrixEnable = false; - mLightCount = 0; - + uint32_t paramLength) + : Program(rsc, shaderText, shaderLength, params, paramLength) { init(rsc); } -ProgramVertex::~ProgramVertex() -{ -} - -static void logMatrix(const char *txt, const float *f) -{ - LOGV("Matrix %s, %p", txt, f); - LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[0], f[4], f[8], f[12]); - LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[1], f[5], f[9], f[13]); - LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[2], f[6], f[10], f[14]); - LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[3], f[7], f[11], f[15]); -} - -void ProgramVertex::setupGL(const Context *rsc, ProgramVertexState *state) -{ - if ((state->mLast.get() == this) && !mDirty) { - return; - } - state->mLast.set(this); - - const float *f = static_cast<const float *>(mConstants[0]->getPtr()); - - glMatrixMode(GL_TEXTURE); - if (mTextureMatrixEnable) { - glLoadMatrixf(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET]); - } else { - glLoadIdentity(); - } - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - if (mLightCount) { - int v = 0; - glEnable(GL_LIGHTING); - glLightModelxv(GL_LIGHT_MODEL_TWO_SIDE, &v); - for (uint32_t ct = 0; ct < mLightCount; ct++) { - const Light *l = mLights[ct].get(); - glEnable(GL_LIGHT0 + ct); - l->setupGL(ct); - } - for (uint32_t ct = mLightCount; ct < MAX_LIGHTS; ct++) { - glDisable(GL_LIGHT0 + ct); - } - } else { - glDisable(GL_LIGHTING); - } - - if (!f) { - LOGE("Must bind constants to vertex program"); +ProgramVertex::~ProgramVertex() { + if (mShaderID) { + mRSC->mShaderCache.cleanupVertex(mShaderID); } - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]); - - mDirty = false; } void ProgramVertex::loadShader(Context *rsc) { Program::loadShader(rsc, GL_VERTEX_SHADER); } -void ProgramVertex::createShader() -{ - mShader.setTo(""); - - mShader.append("varying vec4 varColor;\n"); - mShader.append("varying vec4 varTex0;\n"); - +void ProgramVertex::createShader(Context *rsc) { if (mUserShader.length() > 1) { - mShader.append("uniform mat4 "); - mShader.append(mUniformNames[0]); - mShader.append(";\n"); - - 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); - - // Cannot be complex - rsAssert(!f->getFieldCount()); - 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(e->getFieldName(field)); - mShader.append(";\n"); - } - } + 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()) { + 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; @@ -162,149 +75,115 @@ void ProgramVertex::createShader() rsAssert(0); } - mShader.append(e->getFieldName(field)); + mShader.append(fn); mShader.append(";\n"); } } mShader.append(mUserShader); } else { - mShader.append("attribute vec4 ATTRIB_LegacyPosition;\n"); - mShader.append("attribute vec4 ATTRIB_LegacyColor;\n"); - mShader.append("attribute vec3 ATTRIB_LegacyNormal;\n"); - mShader.append("attribute float ATTRIB_LegacyPointSize;\n"); - mShader.append("attribute vec4 ATTRIB_LegacyTexture;\n"); - - for (uint32_t ct=0; ct < mUniformCount; ct++) { - mShader.append("uniform mat4 "); - mShader.append(mUniformNames[ct]); - mShader.append(";\n"); - } - - mShader.append("void main() {\n"); - mShader.append(" gl_Position = UNI_MVP * ATTRIB_LegacyPosition;\n"); - mShader.append(" gl_PointSize = ATTRIB_LegacyPointSize;\n"); - - mShader.append(" varColor = ATTRIB_LegacyColor;\n"); - if (mTextureMatrixEnable) { - mShader.append(" varTex0 = UNI_TexMatrix * ATTRIB_LegacyTexture;\n"); - } else { - mShader.append(" varTex0 = ATTRIB_LegacyTexture;\n"); - } - //mShader.append(" pos.x = pos.x / 480.0;\n"); - //mShader.append(" pos.y = pos.y / 800.0;\n"); - //mShader.append(" gl_Position = pos;\n"); - mShader.append("}\n"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "ProgramFragment::createShader cannot create program, shader code not defined"); } } -void ProgramVertex::setupGL2(const Context *rsc, ProgramVertexState *state, ShaderCache *sc) -{ - //LOGE("sgl2 vtx1 %x", glGetError()); +void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc) { if ((state->mLast.get() == this) && !mDirty) { - //return; + return; } rsc->checkError("ProgramVertex::setupGL2 start"); - glVertexAttrib4f(1, state->color[0], state->color[1], state->color[2], state->color[3]); - - const float *f = static_cast<const float *>(mConstants[0]->getPtr()); - Matrix mvp; - mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]); - Matrix t; - t.load(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]); - mvp.multiply(&t); - - glUniformMatrix4fv(sc->vtxUniformSlot(0), 1, GL_FALSE, mvp.m); - if (mTextureMatrixEnable) { - glUniformMatrix4fv(sc->vtxUniformSlot(1), 1, GL_FALSE, - &f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET]); - } - - rsc->checkError("ProgramVertex::setupGL2 begin uniforms"); - uint32_t uidx = 1; - for (uint32_t ct=0; ct < mConstantCount; ct++) { - Allocation *alloc = mConstants[ct+1].get(); - if (!alloc) { - continue; + if (!isUserProgram()) { + if (mConstants[0].get() == NULL) { + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Unable to set fixed function emulation matrices because allocation is missing"); + return; } - - 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); - uint32_t offset = e->getFieldOffsetBytes(field); - int32_t slot = sc->vtxUniformSlot(uidx); - - const float *fd = reinterpret_cast<const float *>(&data[offset]); - - //LOGE("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i", slot, offset, ct, field, uidx); - if (slot >= 0) { - switch(f->getComponent().getVectorSize()) { - case 1: - //LOGE("Uniform 1 = %f", fd[0]); - glUniform1fv(slot, 1, fd); - break; - case 2: - //LOGE("Uniform 2 = %f %f", fd[0], fd[1]); - glUniform2fv(slot, 1, fd); - break; - case 3: - //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]); - glUniform3fv(slot, 1, fd); - break; - case 4: - //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]); - glUniform4fv(slot, 1, fd); - break; - default: - rsAssert(0); - } - } - uidx ++; + float *f = static_cast<float *>(mConstants[0]->getPtr()); + Matrix mvp; + mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]); + Matrix t; + t.load(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]); + mvp.multiply(&t); + for (uint32_t i = 0; i < 16; i ++) { + f[RS_PROGRAM_VERTEX_MVP_OFFSET + i] = mvp.m[i]; } } - for (uint32_t ct=0; ct < mConstantCount; ct++) { - uint32_t glSlot = sc->vtxUniformSlot(ct + 1); - - } + rsc->checkError("ProgramVertex::setupGL2 begin uniforms"); + setupUserConstants(rsc, sc, false); state->mLast.set(this); rsc->checkError("ProgramVertex::setupGL2"); } -void ProgramVertex::addLight(const Light *l) -{ - if (mLightCount < MAX_LIGHTS) { - mLights[mLightCount].set(l); - mLightCount++; +void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const { + if (isUserProgram()) { + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Attempting to set fixed function emulation matrix projection on user program"); + return; + } + if (mConstants[0].get() == NULL) { + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Unable to set fixed function emulation matrix projection because allocation is missing"); + return; } -} - -void ProgramVertex::setProjectionMatrix(const rsc_Matrix *m) const -{ float *f = static_cast<float *>(mConstants[0]->getPtr()); memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix)); mDirty = true; } -void ProgramVertex::setModelviewMatrix(const rsc_Matrix *m) const -{ +void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const { + if (isUserProgram()) { + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Attempting to set fixed function emulation matrix modelview on user program"); + return; + } + if (mConstants[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()); memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix)); mDirty = true; } -void ProgramVertex::setTextureMatrix(const rsc_Matrix *m) const -{ +void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const { + if (isUserProgram()) { + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Attempting to set fixed function emulation matrix texture on user program"); + return; + } + if (mConstants[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()); memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix)); mDirty = true; } -void ProgramVertex::transformToScreen(const Context *rsc, float *v4out, const float *v3in) const -{ +void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const { + if (isUserProgram()) { + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Attempting to get fixed function emulation matrix projection on user program"); + return; + } + if (mConstants[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()); + memcpy(m, &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], sizeof(rsc_Matrix)); +} + +void ProgramVertex::transformToScreen(Context *rsc, float *v4out, const float *v3in) const { + if (isUserProgram()) { + return; + } float *f = static_cast<float *>(mConstants[0]->getPtr()); Matrix mvp; mvp.loadMultiply((Matrix *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], @@ -312,94 +191,101 @@ void ProgramVertex::transformToScreen(const Context *rsc, float *v4out, const fl mvp.vectorMultiply(v4out, v3in); } -void ProgramVertex::initAddUserElement(const Element *e, String8 *names, 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, count, prefix); - } else { - String8 tmp(prefix); - tmp.append(e->getFieldName(ct)); - names[*count].setTo(tmp.string()); - (*count)++; - } - } -} - - -void ProgramVertex::init(Context *rsc) -{ - mAttribCount = 0; +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, &mAttribCount, "ATTRIB_"); + initAddUserElement(mInputElements[ct].get(), mAttribNames, NULL, &attribCount, RS_SHADER_ATTR); } - - mUniformCount = 1; - mUniformNames[0].setTo("UNI_MVP"); for (uint32_t ct=0; ct < mConstantCount; ct++) { - initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, "UNI_"); + initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI); } - } else { - mUniformCount = 2; - mUniformNames[0].setTo("UNI_MVP"); - mUniformNames[1].setTo("UNI_TexMatrix"); } + createShader(rsc); +} + +void ProgramVertex::serialize(OStream *stream) const { +} - createShader(); +ProgramVertex *ProgramVertex::createFromStream(Context *rsc, IStream *stream) { + return NULL; } /////////////////////////////////////////////////////////////////////// -ProgramVertexState::ProgramVertexState() -{ +ProgramVertexState::ProgramVertexState() { } -ProgramVertexState::~ProgramVertexState() -{ +ProgramVertexState::~ProgramVertexState() { } -void ProgramVertexState::init(Context *rsc, int32_t w, int32_t h) -{ - RsElement e = (RsElement) Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); - - rsi_TypeBegin(rsc, e); - rsi_TypeAdd(rsc, RS_DIMENSION_X, 48); - mAllocType.set((Type *)rsi_TypeCreate(rsc)); +void ProgramVertexState::init(Context *rsc) { + const Element *matrixElem = Element::create(rsc, RS_TYPE_MATRIX_4X4, RS_KIND_USER, false, 1); + const Element *f2Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); + const Element *f3Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); + const Element *f4Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); + + rsc->mStateElement.elementBuilderBegin(); + rsc->mStateElement.elementBuilderAdd(matrixElem, "MV", 1); + rsc->mStateElement.elementBuilderAdd(matrixElem, "P", 1); + rsc->mStateElement.elementBuilderAdd(matrixElem, "TexMatrix", 1); + rsc->mStateElement.elementBuilderAdd(matrixElem, "MVP", 1); + const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc); + + rsc->mStateElement.elementBuilderBegin(); + rsc->mStateElement.elementBuilderAdd(f4Elem, "position", 1); + rsc->mStateElement.elementBuilderAdd(f4Elem, "color", 1); + rsc->mStateElement.elementBuilderAdd(f3Elem, "normal", 1); + rsc->mStateElement.elementBuilderAdd(f2Elem, "texture0", 1); + const Element *attrElem = rsc->mStateElement.elementBuilderCreate(rsc); + + Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false); + + String8 shaderString(RS_SHADER_INTERNAL); + shaderString.append("varying vec4 varColor;\n"); + shaderString.append("varying vec2 varTex0;\n"); + shaderString.append("void main() {\n"); + shaderString.append(" gl_Position = UNI_MVP * ATTRIB_position;\n"); + shaderString.append(" gl_PointSize = 1.0;\n"); + shaderString.append(" varColor = ATTRIB_color;\n"); + shaderString.append(" varTex0 = ATTRIB_texture0;\n"); + shaderString.append("}\n"); + + uint32_t tmp[4]; + tmp[0] = RS_PROGRAM_PARAM_CONSTANT; + tmp[1] = (uint32_t)inputType; + tmp[2] = RS_PROGRAM_PARAM_INPUT; + tmp[3] = (uint32_t)attrElem; + + 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); + pv->bindAllocation(rsc, alloc, 0); - ProgramVertex *pv = new ProgramVertex(rsc, false); - Allocation *alloc = (Allocation *)rsi_AllocationCreateTyped(rsc, mAllocType.get()); mDefaultAlloc.set(alloc); mDefault.set(pv); - pv->init(rsc); - pv->bindAllocation(alloc, 0); - color[0] = 1.f; - color[1] = 1.f; - color[2] = 1.f; - color[3] = 1.f; - - updateSize(rsc, w, h); + updateSize(rsc); } -void ProgramVertexState::updateSize(Context *rsc, int32_t w, int32_t h) -{ +void ProgramVertexState::updateSize(Context *rsc) { + float *f = static_cast<float *>(mDefaultAlloc->getPtr()); + Matrix m; - m.loadOrtho(0,w, h,0, -1,1); - mDefaultAlloc->subData(RS_PROGRAM_VERTEX_PROJECTION_OFFSET, 16, &m.m[0], 16*4); + 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)); m.loadIdentity(); - mDefaultAlloc->subData(RS_PROGRAM_VERTEX_MODELVIEW_OFFSET, 16, &m.m[0], 16*4); + memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m.m, sizeof(m)); + memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m.m, sizeof(m)); } -void ProgramVertexState::deinit(Context *rsc) -{ +void ProgramVertexState::deinit(Context *rsc) { mDefaultAlloc.clear(); mDefault.clear(); - mAllocType.clear(); mLast.clear(); } @@ -407,23 +293,13 @@ void ProgramVertexState::deinit(Context *rsc) namespace android { namespace renderscript { - -RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, bool texMat) -{ - ProgramVertex *pv = new ProgramVertex(rsc, texMat); - pv->incUserRef(); - return pv; -} - -RsProgramVertex rsi_ProgramVertexCreate2(Context *rsc, const char * shaderText, +RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, const char * shaderText, uint32_t shaderLength, const uint32_t * params, - uint32_t paramLength) -{ + uint32_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 28554cc..2a5c863 100644 --- a/libs/rs/rsProgramVertex.h +++ b/libs/rs/rsProgramVertex.h @@ -25,67 +25,44 @@ namespace renderscript { class ProgramVertexState; -class ProgramVertex : public Program -{ +class ProgramVertex : public Program { public: - const static uint32_t MAX_LIGHTS = 8; - ProgramVertex(Context *,const char * shaderText, uint32_t shaderLength, const uint32_t * params, uint32_t paramLength); - ProgramVertex(Context *, bool texMat); virtual ~ProgramVertex(); - virtual void setupGL(const Context *rsc, ProgramVertexState *state); - virtual void setupGL2(const Context *rsc, ProgramVertexState *state, ShaderCache *sc); - - - void setTextureMatrixEnable(bool e) {mTextureMatrixEnable = e;} - void addLight(const Light *); + virtual void setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc); - void setProjectionMatrix(const rsc_Matrix *) const; - void setModelviewMatrix(const rsc_Matrix *) const; - void setTextureMatrix(const rsc_Matrix *) const; + void setProjectionMatrix(Context *, const rsc_Matrix *) const; + void getProjectionMatrix(Context *, rsc_Matrix *) const; + void setModelviewMatrix(Context *, const rsc_Matrix *) const; + void setTextureMatrix(Context *, const rsc_Matrix *) const; - void transformToScreen(const Context *, float *v4out, const float *v3in) const; + void transformToScreen(Context *, float *v4out, const float *v3in) const; - virtual void createShader(); + virtual void createShader(Context *); virtual void loadShader(Context *); virtual void init(Context *); - -protected: - uint32_t mLightCount; - ObjectBaseRef<const Light> mLights[MAX_LIGHTS]; - - // Hacks to create a program for now - bool mTextureMatrixEnable; - -private: - void initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix); + virtual void serialize(OStream *stream) const; + virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_VERTEX; } + static ProgramVertex *createFromStream(Context *rsc, IStream *stream); }; - -class ProgramVertexState -{ +class ProgramVertexState { public: ProgramVertexState(); ~ProgramVertexState(); - void init(Context *rsc, int32_t w, int32_t h); + void init(Context *rsc); void deinit(Context *rsc); - void updateSize(Context *rsc, int32_t w, int32_t h); + void updateSize(Context *rsc); ObjectBaseRef<ProgramVertex> mDefault; ObjectBaseRef<ProgramVertex> mLast; ObjectBaseRef<Allocation> mDefaultAlloc; - - ObjectBaseRef<Type> mAllocType; - - - float color[4]; }; - } } #endif diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp index 5693c8a..c80aecc 100644 --- a/libs/rs/rsSampler.cpp +++ b/libs/rs/rsSampler.cpp @@ -14,10 +14,16 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include <GLES/gl.h> #include <GLES/glext.h> - #include "rsContext.h" +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> +#endif //ANDROID_RS_BUILD_FOR_HOST + #include "rsSampler.h" @@ -25,10 +31,7 @@ using namespace android; using namespace android::renderscript; -Sampler::Sampler(Context *rsc) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +Sampler::Sampler(Context *rsc) : ObjectBase(rsc) { // Should not get called. rsAssert(0); } @@ -38,78 +41,98 @@ Sampler::Sampler(Context *rsc, RsSamplerValue minFilter, RsSamplerValue wrapS, RsSamplerValue wrapT, - RsSamplerValue wrapR) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; + RsSamplerValue wrapR, + float aniso) : ObjectBase(rsc) { mMagFilter = magFilter; mMinFilter = minFilter; mWrapS = wrapS; mWrapT = wrapT; mWrapR = wrapR; + mAniso = aniso; } -Sampler::~Sampler() -{ +Sampler::~Sampler() { } -void Sampler::setupGL(const Context *rsc, bool npot) -{ +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 }; - bool forceNonMip = false; - if (!rsc->ext_OES_texture_npot() && npot) { - forceNonMip = true; - } + 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, + }; - if ((mMinFilter == RS_SAMPLER_LINEAR_MIP_LINEAR) && forceNonMip) { - if (rsc->ext_GL_IMG_texture_npot()) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + 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 { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]); + 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]); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, trans[mMagFilter]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, trans[mWrapS]); - glTexParameteri(GL_TEXTURE_2D, 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("ProgramFragment::setupGL2 tex env"); + rsc->checkError("Sampler::setupGL2 tex env"); } -void Sampler::bindToContext(SamplerState *ss, uint32_t slot) -{ +void Sampler::bindToContext(SamplerState *ss, uint32_t slot) { ss->mSamplers[slot].set(this); mBoundSlot = slot; } -void Sampler::unbindFromContext(SamplerState *ss) -{ +void Sampler::unbindFromContext(SamplerState *ss) { int32_t slot = mBoundSlot; mBoundSlot = -1; ss->mSamplers[slot].clear(); } -/* -void SamplerState::setupGL() -{ - for (uint32_t ct=0; ct < RS_MAX_SAMPLER_SLOT; ct++) { - Sampler *s = mSamplers[ct].get(); - if (s) { - s->setupGL(rsc); - } else { - glBindTexture(GL_TEXTURE_2D, 0); - } - } -}*/ + +void Sampler::serialize(OStream *stream) const { +} + +Sampler *Sampler::createFromStream(Context *rsc, IStream *stream) { + return NULL; +} //////////////////////////////// @@ -117,8 +140,7 @@ namespace android { namespace renderscript { -void rsi_SamplerBegin(Context *rsc) -{ +void rsi_SamplerBegin(Context *rsc) { SamplerState * ss = &rsc->mStateSampler; ss->mMagFilter = RS_SAMPLER_LINEAR; @@ -126,13 +148,13 @@ void rsi_SamplerBegin(Context *rsc) 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) -{ +void rsi_SamplerSet(Context *rsc, RsSamplerParam param, RsSamplerValue value) { SamplerState * ss = &rsc->mStateSampler; - switch(param) { + switch (param) { case RS_SAMPLER_MAG_FILTER: ss->mMagFilter = value; break; @@ -148,24 +170,37 @@ void rsi_SamplerSet(Context *rsc, RsSamplerParam param, RsSamplerValue value) case RS_SAMPLER_WRAP_R: ss->mWrapR = value; break; + default: + LOGE("Attempting to set invalid value on sampler"); + break; } - } -RsSampler rsi_SamplerCreate(Context *rsc) -{ +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->mWrapR, + ss->mAniso); s->incUserRef(); return s; } - }} diff --git a/libs/rs/rsSampler.h b/libs/rs/rsSampler.h index 0506081..737bb8b 100644 --- a/libs/rs/rsSampler.h +++ b/libs/rs/rsSampler.h @@ -28,58 +28,55 @@ const static uint32_t RS_MAX_SAMPLER_SLOT = 16; class SamplerState; -class Sampler : public ObjectBase -{ +class Sampler : public ObjectBase { public: Sampler(Context *, RsSamplerValue magFilter, RsSamplerValue minFilter, RsSamplerValue wrapS, RsSamplerValue wrapT, - RsSamplerValue wrapR); + RsSamplerValue wrapR, + float aniso = 1.0f); virtual ~Sampler(); void bind(Allocation *); - void setupGL(const Context *, bool npot); + void setupGL(const Context *, const Allocation *); void bindToContext(SamplerState *, uint32_t slot); void unbindFromContext(SamplerState *); + virtual void serialize(OStream *stream) const; + 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; int32_t mBoundSlot; private: Sampler(Context *); - }; -class SamplerState -{ +class SamplerState { public: - RsSamplerValue mMagFilter; RsSamplerValue mMinFilter; RsSamplerValue mWrapS; RsSamplerValue mWrapT; RsSamplerValue mWrapR; - + float mAniso; ObjectBaseRef<Sampler> mSamplers[RS_MAX_SAMPLER_SLOT]; - - //void setupGL(); - }; - - } } #endif //ANDROID_RS_SAMPLER_H diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp index a33933b..efdc626 100644 --- a/libs/rs/rsScript.cpp +++ b/libs/rs/rsScript.cpp @@ -19,98 +19,132 @@ using namespace android; using namespace android::renderscript; -Script::Script(Context *rsc) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +Script::Script(Context *rsc) : ObjectBase(rsc) { memset(&mEnviroment, 0, sizeof(mEnviroment)); - mEnviroment.mClearColor[0] = 0; - mEnviroment.mClearColor[1] = 0; - mEnviroment.mClearColor[2] = 0; - mEnviroment.mClearColor[3] = 1; - mEnviroment.mClearDepth = 1; - mEnviroment.mClearStencil = 0; - mEnviroment.mIsRoot = false; + + mSlots = NULL; + mTypes = NULL; +} + +Script::~Script() { + if (mSlots) { + delete [] mSlots; + mSlots = NULL; + } + if (mTypes) { + delete [] mTypes; + mTypes = NULL; + } +} + +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("Script::setSlot unable to set allocation, invalid slot index"); + return; + } + + mSlots[slot].set(a); +} + +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); + //} + } } -Script::~Script() -{ +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; + } else { + LOGV("Calling setVarObj on slot = %i which is null. This is dangerous because the script will not hold a ref count on the object.", slot); + } } namespace android { namespace renderscript { - -void rsi_ScriptBindAllocation(Context * rsc, RsScript vs, RsAllocation va, uint32_t slot) -{ +void rsi_ScriptBindAllocation(Context * rsc, RsScript vs, RsAllocation va, uint32_t slot) { Script *s = static_cast<Script *>(vs); - s->mSlots[slot].set(static_cast<Allocation *>(va)); + Allocation *a = static_cast<Allocation *>(va); + s->setSlot(slot, a); + //LOGE("rsi_ScriptBindAllocation %i %p %p", slot, a, a->getPtr()); } -void rsi_ScriptSetClearColor(Context * rsc, RsScript vs, float r, float g, float b, float a) -{ +void rsi_ScriptSetTimeZone(Context * rsc, RsScript vs, const char * timeZone, uint32_t length) { Script *s = static_cast<Script *>(vs); - s->mEnviroment.mClearColor[0] = r; - s->mEnviroment.mClearColor[1] = g; - s->mEnviroment.mClearColor[2] = b; - s->mEnviroment.mClearColor[3] = a; + s->mEnviroment.mTimeZone = timeZone; } -void rsi_ScriptSetTimeZone(Context * rsc, RsScript vs, const char * timeZone, uint32_t length) -{ +void rsi_ScriptInvoke(Context *rsc, RsScript vs, uint32_t slot) { Script *s = static_cast<Script *>(vs); - s->mEnviroment.mTimeZone = timeZone; + s->Invoke(rsc, slot, NULL, 0); } -void rsi_ScriptSetClearDepth(Context * rsc, RsScript vs, float v) -{ + +void rsi_ScriptInvokeData(Context *rsc, RsScript vs, uint32_t slot, void *data) { Script *s = static_cast<Script *>(vs); - s->mEnviroment.mClearDepth = v; + s->Invoke(rsc, slot, NULL, 0); } -void rsi_ScriptSetClearStencil(Context * rsc, RsScript vs, uint32_t v) -{ +void rsi_ScriptInvokeV(Context *rsc, RsScript vs, uint32_t slot, const void *data, uint32_t len) { Script *s = static_cast<Script *>(vs); - s->mEnviroment.mClearStencil = v; + s->Invoke(rsc, slot, data, len); } -void rsi_ScriptSetType(Context * rsc, RsType vt, uint32_t slot, bool writable, const char *name) -{ - ScriptCState *ss = &rsc->mScriptC; - const Type *t = static_cast<const Type *>(vt); - ss->mConstantBufferTypes[slot].set(t); - ss->mSlotWritable[slot] = writable; - if (name) { - ss->mSlotNames[slot].setTo(name); - } else { - ss->mSlotNames[slot].setTo(""); - } +void rsi_ScriptSetVarI(Context *rsc, RsScript vs, uint32_t slot, int value) { + Script *s = static_cast<Script *>(vs); + s->setVar(slot, &value, sizeof(value)); } -void rsi_ScriptSetInvoke(Context *rsc, const char *name, uint32_t slot) -{ - ScriptCState *ss = &rsc->mScriptC; - ss->mInvokableNames[slot] = name; +void rsi_ScriptSetVarObj(Context *rsc, RsScript vs, uint32_t slot, RsObjectBase value) { + Script *s = static_cast<Script *>(vs); + ObjectBase *o = static_cast<ObjectBase *>(value); + s->setVarObj(slot, o); } -void rsi_ScriptInvoke(Context *rsc, RsScript vs, uint32_t slot) -{ +void rsi_ScriptSetVarJ(Context *rsc, RsScript vs, uint32_t slot, long long value) { Script *s = static_cast<Script *>(vs); - if (s->mEnviroment.mInvokables[slot] == NULL) { - rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script"); - return; - } - s->setupScript(); - s->mEnviroment.mInvokables[slot](); + s->setVar(slot, &value, sizeof(value)); } +void rsi_ScriptSetVarF(Context *rsc, RsScript vs, uint32_t slot, float value) { + Script *s = static_cast<Script *>(vs); + s->setVar(slot, &value, sizeof(value)); +} -void rsi_ScriptSetRoot(Context * rsc, bool isRoot) -{ - ScriptCState *ss = &rsc->mScriptC; - ss->mScript->mEnviroment.mIsRoot = isRoot; +void rsi_ScriptSetVarD(Context *rsc, RsScript vs, uint32_t slot, double value) { + Script *s = static_cast<Script *>(vs); + s->setVar(slot, &value, sizeof(value)); } +void rsi_ScriptSetVarV(Context *rsc, RsScript vs, uint32_t slot, const void *data, uint32_t len) { + const float *fp = (const float *)data; + Script *s = static_cast<Script *>(vs); + s->setVar(slot, data, len); +} } } diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h index 5f4a536..bad095b 100644 --- a/libs/rs/rsScript.h +++ b/libs/rs/rsScript.h @@ -27,54 +27,58 @@ namespace renderscript { class ProgramVertex; class ProgramFragment; class ProgramRaster; -class ProgramFragmentStore; +class ProgramStore; -#define MAX_SCRIPT_BANKS 16 - -class Script : public ObjectBase -{ +class Script : public ObjectBase { public: typedef void (* InvokeFunc_t)(void); Script(Context *); virtual ~Script(); - struct Enviroment_t { - bool mIsRoot; - float mClearColor[4]; - float mClearDepth; - uint32_t mClearStencil; - - uint32_t mStartTimeMillis; + int64_t mStartTimeMillis; + int64_t mLastDtTime; const char* mTimeZone; ObjectBaseRef<ProgramVertex> mVertex; ObjectBaseRef<ProgramFragment> mFragment; ObjectBaseRef<ProgramRaster> mRaster; - ObjectBaseRef<ProgramFragmentStore> mFragmentStore; - InvokeFunc_t mInvokables[MAX_SCRIPT_BANKS]; + ObjectBaseRef<ProgramStore> mFragmentStore; + + uint32_t mInvokeFunctionCount; + InvokeFunc_t *mInvokeFunctions; + uint32_t mFieldCount; + void ** mFieldAddress; + char * mScriptText; uint32_t mScriptTextLength; + + bool mIsThreadable; }; Enviroment_t mEnviroment; - uint32_t mCounstantBufferCount; - + void initSlots(); + void setSlot(uint32_t slot, Allocation *a); + void setVar(uint32_t slot, const void *val, uint32_t len); + void setVarObj(uint32_t slot, ObjectBase *val); - ObjectBaseRef<Allocation> mSlots[MAX_SCRIPT_BANKS]; - ObjectBaseRef<const Type> mTypes[MAX_SCRIPT_BANKS]; - String8 mSlotNames[MAX_SCRIPT_BANKS]; - bool mSlotWritable[MAX_SCRIPT_BANKS]; + virtual void runForEach(Context *rsc, + const Allocation * ain, + Allocation * aout, + const void * usr, + const RsScriptCall *sc = NULL) = 0; + virtual void Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) = 0; + virtual void setupScript(Context *rsc) = 0; + virtual uint32_t run(Context *) = 0; +protected: + ObjectBaseRef<Allocation> *mSlots; + ObjectBaseRef<const Type> *mTypes; - - virtual void setupScript() = 0; - virtual uint32_t run(Context *, uint32_t launchID) = 0; }; - } } #endif diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index f4d2451..3858e1c 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -17,9 +17,11 @@ #include "rsContext.h" #include "rsScriptC.h" #include "rsMatrix.h" - -#include "acc/acc.h" #include "utils/Timers.h" +#include "utils/StopWatch.h" +extern "C" { +#include "libdex/ZipArchive.h" +} #include <GLES/gl.h> #include <GLES/glext.h> @@ -32,415 +34,602 @@ 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); + } -ScriptC::ScriptC(Context *rsc) : Script(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; - mAccScript = NULL; + // 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) { + LOGD(">>>> ScriptC ctor called, obj=%p", this); + mBccScript = NULL; memset(&mProgram, 0, sizeof(mProgram)); } -ScriptC::~ScriptC() -{ - if (mAccScript) { - accDeleteScript(mAccScript); +ScriptC::~ScriptC() { + LOGD(">>>> ~ScriptC() mBccScript = %p", mBccScript); + if (mBccScript) { + bccDisposeScript(mBccScript); + LOGD(">>>> ~ScriptC(mBCCScript)"); } free(mEnviroment.mScriptText); mEnviroment.mScriptText = NULL; } -void ScriptC::setupScript() -{ - for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { - if (mProgram.mSlotPointers[ct]) { - *mProgram.mSlotPointers[ct] = mSlots[ct]->getPtr(); +void ScriptC::setupScript(Context *rsc) { + mEnviroment.mStartTimeMillis + = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); + + for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) { + if (mSlots[ct].get() && !mTypes[ct].get()) { + mTypes[ct].set(mSlots[ct]->getType()); + } + + if (!mTypes[ct].get()) + continue; + void *ptr = NULL; + 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; } } } - -uint32_t ScriptC::run(Context *rsc, uint32_t launchIndex) -{ - if (mProgram.mScript == NULL) { - rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script"); - return 0; +const Allocation *ScriptC::ptrToAllocation(const void *ptr) const { + if (!ptr) { + return NULL; } + for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) { + if (!mSlots[ct].get()) + continue; + if (mSlots[ct]->getPtr() == ptr) { + return mSlots[ct].get(); + } + } + LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr); + return NULL; +} - Context::ScriptTLSStruct * tls = - (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); +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->setFragmentStore(mEnviroment.mFragmentStore.get()); + rsc->setProgramStore(mEnviroment.mFragmentStore.get()); } if (mEnviroment.mFragment.get()) { - rsc->setFragment(mEnviroment.mFragment.get()); + rsc->setProgramFragment(mEnviroment.mFragment.get()); } if (mEnviroment.mVertex.get()) { - rsc->setVertex(mEnviroment.mVertex.get()); + rsc->setProgramVertex(mEnviroment.mVertex.get()); } if (mEnviroment.mRaster.get()) { - rsc->setRaster(mEnviroment.mRaster.get()); + rsc->setProgramRaster(mEnviroment.mRaster.get()); } +} - if (launchIndex == 0) { - mEnviroment.mStartTimeMillis - = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); +uint32_t ScriptC::run(Context *rsc) { + if (mProgram.mRoot == NULL) { + rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script"); + return 0; } - setupScript(); + + setupGLState(rsc); + setupScript(rsc); uint32_t ret = 0; - tls->mScript = this; - ret = mProgram.mScript(launchIndex); - tls->mScript = NULL; + Script * oldTLS = setTLS(this); + + if (rsc->props.mLogScripts) { + LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mProgram.mRoot); + } + + ret = mProgram.mRoot(); + + if (rsc->props.mLogScripts) { + LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret); + } + + setTLS(oldTLS); return ret; } -ScriptCState::ScriptCState() -{ - mScript = NULL; - clear(); +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; + } + } + } } -ScriptCState::~ScriptCState() -{ - delete mScript; - mScript = NULL; +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 ScriptCState::clear() -{ - for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) { - mConstantBufferTypes[ct].clear(); - mSlotNames[ct].setTo(""); - mInvokableNames[ct].setTo(""); - mSlotWritable[ct] = false; +void ScriptC::runForEach(Context *rsc, + const Allocation * ain, + Allocation * aout, + const void * usr, + 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; } - delete mScript; - mScript = new ScriptC(NULL); + 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; + } - mInt32Defines.clear(); - mFloatDefines.clear(); + 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); + + 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); } -static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) -{ - const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name); +void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) { + if ((slot >= mEnviroment.mInvokeFunctionCount) || + (mEnviroment.mInvokeFunctions[slot] == NULL)) { + 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); + } + + setTLS(oldTLS); +} + +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; + } else if (!strcmp(name, "__clearThreadable")) { + s->mEnviroment.mIsThreadable = false; + return NULL; + } + sym = ScriptCState::lookupSymbol(name); + if (!sym) { + sym = ScriptCState::lookupSymbolCL(name); + } + if (!sym) { + sym = ScriptCState::lookupSymbolGL(name); + } if (sym) { + s->mEnviroment.mIsThreadable &= sym->threadable; return sym->mPtr; } LOGE("ScriptC sym lookup failed for %s", name); return NULL; } -void ScriptCState::runCompiler(Context *rsc, ScriptC *s) -{ - s->mAccScript = accCreateScript(); - String8 tmp; - - rsc->appendNameDefines(&tmp); - appendDecls(&tmp); - appendVarDefines(rsc, &tmp); - appendTypes(rsc, &tmp); - tmp.append("#line 1\n"); - - const char* scriptSource[] = {tmp.string(), s->mEnviroment.mScriptText}; - int scriptLength[] = {tmp.length(), s->mEnviroment.mScriptTextLength} ; - accScriptSource(s->mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength); - accRegisterSymbolCallback(s->mAccScript, symbolLookup, NULL); - accCompileScript(s->mAccScript); - accGetScriptLabel(s->mAccScript, "main", (ACCvoid**) &s->mProgram.mScript); - accGetScriptLabel(s->mAccScript, "init", (ACCvoid**) &s->mProgram.mInit); - rsAssert(s->mProgram.mScript); - - if (!s->mProgram.mScript) { - ACCchar buf[4096]; - ACCsizei len; - accGetScriptInfoLog(s->mAccScript, sizeof(buf), &len, buf); - LOGE("%s", buf); - rsc->setError(RS_ERROR_BAD_SCRIPT, "Error compiling user script."); - return; +#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 (bccLinkBC(s->mBccScript, + resName, + NULL /*rs_runtime_lib_bc*/, + 1 /*rs_runtime_lib_bc_size*/ + /*"1" means skip buffer here, and let libbcc decide*/, + 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); + + s->mProgram.mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(s->mBccScript, "root")); + s->mProgram.mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(s->mBccScript, "init")); if (s->mProgram.mInit) { s->mProgram.mInit(); } - for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { - if (mSlotNames[ct].length() > 0) { - accGetScriptLabel(s->mAccScript, - mSlotNames[ct].string(), - (ACCvoid**) &s->mProgram.mSlotPointers[ct]); - } + 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); } - for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { - if (mInvokableNames[ct].length() > 0) { - accGetScriptLabel(s->mAccScript, - mInvokableNames[ct].string(), - (ACCvoid**) &s->mEnviroment.mInvokables[ct]); - } + 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(); } s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); - s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore()); + s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore()); s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster()); - if (s->mProgram.mScript) { - const static int pragmaMax = 16; - ACCsizei pragmaCount; - ACCchar * str[pragmaMax]; - accGetPragmas(s->mAccScript, &pragmaCount, pragmaMax, &str[0]); + 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); - for (int ct=0; ct < pragmaCount; ct+=2) { - if (!strcmp(str[ct], "version")) { + for (size_t i=0; i < pragmaCount; ++i) { + //LOGE("pragma %s %s", keys[i], values[i]); + if (!strcmp(keys[i], "version")) { + if (!strcmp(values[i], "1")) { continue; } + LOGE("Invalid version pragma value: %s\n", values[i]); + return false; + } - if (!strcmp(str[ct], "stateVertex")) { - if (!strcmp(str[ct+1], "default")) { - continue; - } - if (!strcmp(str[ct+1], "parent")) { - s->mEnviroment.mVertex.clear(); - continue; - } - ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]); - if (pv != NULL) { - s->mEnviroment.mVertex.set(pv); - continue; - } - LOGE("Unreconized value %s passed to stateVertex", str[ct+1]); + if (!strcmp(keys[i], "stateVertex")) { + if (!strcmp(values[i], "default")) { + continue; } - - if (!strcmp(str[ct], "stateRaster")) { - if (!strcmp(str[ct+1], "default")) { - continue; - } - if (!strcmp(str[ct+1], "parent")) { - s->mEnviroment.mRaster.clear(); - continue; - } - ProgramRaster * pr = (ProgramRaster *)rsc->lookupName(str[ct+1]); - if (pr != NULL) { - s->mEnviroment.mRaster.set(pr); - continue; - } - LOGE("Unreconized value %s passed to stateRaster", str[ct+1]); + if (!strcmp(values[i], "parent")) { + s->mEnviroment.mVertex.clear(); + continue; } + LOGE("Unrecognized value %s passed to stateVertex", values[i]); + return false; + } - if (!strcmp(str[ct], "stateFragment")) { - if (!strcmp(str[ct+1], "default")) { - continue; - } - if (!strcmp(str[ct+1], "parent")) { - s->mEnviroment.mFragment.clear(); - continue; - } - ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]); - if (pf != NULL) { - s->mEnviroment.mFragment.set(pf); - continue; - } - LOGE("Unreconized value %s passed to stateFragment", str[ct+1]); + if (!strcmp(keys[i], "stateRaster")) { + if (!strcmp(values[i], "default")) { + continue; } - - if (!strcmp(str[ct], "stateStore")) { - if (!strcmp(str[ct+1], "default")) { - continue; - } - if (!strcmp(str[ct+1], "parent")) { - s->mEnviroment.mFragmentStore.clear(); - continue; - } - ProgramFragmentStore * pfs = - (ProgramFragmentStore *)rsc->lookupName(str[ct+1]); - if (pfs != NULL) { - s->mEnviroment.mFragmentStore.set(pfs); - continue; - } - LOGE("Unreconized value %s passed to stateStore", str[ct+1]); + if (!strcmp(values[i], "parent")) { + s->mEnviroment.mRaster.clear(); + continue; } - + LOGE("Unrecognized value %s passed to stateRaster", values[i]); + return false; } - - } else { - // Deal with an error. - } -} - -static void appendElementBody(String8 *s, const Element *e) -{ - s->append(" {\n"); - for (size_t ct2=0; ct2 < e->getFieldCount(); ct2++) { - const Element *c = e->getField(ct2); - s->append(" "); - s->append(c->getCType()); - s->append(" "); - s->append(e->getFieldName(ct2)); - s->append(";\n"); - } - s->append("}"); -} - -void ScriptCState::appendVarDefines(const Context *rsc, String8 *str) -{ - char buf[256]; - if (rsc->props.mLogScripts) { - LOGD("appendVarDefines mInt32Defines.size()=%d mFloatDefines.size()=%d\n", - mInt32Defines.size(), mFloatDefines.size()); - } - for (size_t ct=0; ct < mInt32Defines.size(); ct++) { - str->append("#define "); - str->append(mInt32Defines.keyAt(ct)); - str->append(" "); - sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct)); - str->append(buf); - } - for (size_t ct=0; ct < mFloatDefines.size(); ct++) { - str->append("#define "); - str->append(mFloatDefines.keyAt(ct)); - str->append(" "); - sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct)); - str->append(buf); - } -} - - - -void ScriptCState::appendTypes(const Context *rsc, String8 *str) -{ - char buf[256]; - String8 tmp; - - str->append("struct vecF32_2_s {float x; float y;};\n"); - str->append("struct vecF32_3_s {float x; float y; float z;};\n"); - str->append("struct vecF32_4_s {float x; float y; float z; float w;};\n"); - str->append("struct vecU8_4_s {char r; char g; char b; char a;};\n"); - str->append("#define vecF32_2_t struct vecF32_2_s\n"); - str->append("#define vecF32_3_t struct vecF32_3_s\n"); - str->append("#define vecF32_4_t struct vecF32_4_s\n"); - str->append("#define vecU8_4_t struct vecU8_4_s\n"); - str->append("#define vecI8_4_t struct vecU8_4_s\n"); - - for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) { - const Type *t = mConstantBufferTypes[ct].get(); - if (!t) { - continue; - } - const Element *e = t->getElement(); - if (e->getName() && (e->getFieldCount() > 1)) { - String8 s("struct struct_"); - s.append(e->getName()); - s.append(e->getCStructBody()); - s.append(";\n"); - - s.append("#define "); - s.append(e->getName()); - s.append("_t struct struct_"); - s.append(e->getName()); - s.append("\n\n"); - if (rsc->props.mLogScripts) { - LOGV("%s", static_cast<const char*>(s)); + if (!strcmp(keys[i], "stateFragment")) { + if (!strcmp(values[i], "default")) { + continue; + } + if (!strcmp(values[i], "parent")) { + s->mEnviroment.mFragment.clear(); + continue; } - str->append(s); + LOGE("Unrecognized value %s passed to stateFragment", values[i]); + return false; } - if (mSlotNames[ct].length() > 0) { - String8 s; - if (e->getName()) { - // Use the named struct - s.setTo(e->getName()); - } else { - // create an struct named from the slot. - s.setTo("struct "); - s.append(mSlotNames[ct]); - s.append("_s"); - s.append(e->getCStructBody()); - //appendElementBody(&s, e); - s.append(";\n"); - s.append("struct "); - s.append(mSlotNames[ct]); - s.append("_s"); + if (!strcmp(keys[i], "stateStore")) { + if (!strcmp(values[i], "default")) { + continue; } - - s.append(" * "); - s.append(mSlotNames[ct]); - s.append(";\n"); - if (rsc->props.mLogScripts) { - LOGV("%s", static_cast<const char*>(s)); + if (!strcmp(values[i], "parent")) { + s->mEnviroment.mFragmentStore.clear(); + continue; } - str->append(s); + LOGE("Unrecognized value %s passed to stateStore", values[i]); + return false; } } + return true; } - namespace android { namespace renderscript { -void rsi_ScriptCBegin(Context * rsc) -{ - ScriptCState *ss = &rsc->mScriptC; - ss->clear(); +void rsi_ScriptCBegin(Context * rsc) { } -void rsi_ScriptCSetScript(Context * rsc, void *vp) -{ - rsAssert(0); - //ScriptCState *ss = &rsc->mScriptC; - //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp); -} - -void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) -{ +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->mScript->mEnviroment.mScriptText = t; - ss->mScript->mEnviroment.mScriptTextLength = len; + ss->mScriptText = t; + ss->mScriptLen = len; } -RsScript rsi_ScriptCCreate(Context * rsc) +RsScript rsi_ScriptCCreate(Context *rsc, + const char *packageName /* deprecated */, + const char *resName, + const char *cacheDir) { ScriptCState *ss = &rsc->mScriptC; - ScriptC *s = ss->mScript; - ss->mScript = NULL; - - ss->runCompiler(rsc, s); + ScriptC *s = new ScriptC(rsc); + s->mEnviroment.mScriptText = ss->mScriptText; + s->mEnviroment.mScriptTextLength = ss->mScriptLen; + ss->mScriptText = NULL; + ss->mScriptLen = 0; s->incUserRef(); - s->setContext(rsc); - for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { - s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get()); - s->mSlotNames[ct] = ss->mSlotNames[ct]; - s->mSlotWritable[ct] = ss->mSlotWritable[ct]; - } - ss->clear(); + if (!ss->runCompiler(rsc, s, resName, cacheDir)) { + // Error during compile, destroy s and return null. + delete s; + return NULL; + } return s; } -void rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value) -{ - ScriptCState *ss = &rsc->mScriptC; - ss->mFloatDefines.add(String8(name), value); } - -void rsi_ScriptCSetDefineI32(Context *rsc, const char* name, int32_t value) -{ - ScriptCState *ss = &rsc->mScriptC; - ss->mInt32Defines.add(String8(name), value); } - -} -} - - diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h index 35abadf..7143c67 100644 --- a/libs/rs/rsScriptC.h +++ b/libs/rs/rsScriptC.h @@ -21,20 +21,16 @@ #include "RenderScriptEnv.h" -#include <utils/KeyedVector.h> - -struct ACCscript; +#include <bcc/bcc.h> // --------------------------------------------------------------------------- namespace android { namespace renderscript { - -class ScriptC : public Script -{ +class ScriptC : public Script { public: - typedef int (*RunScript_t)(uint32_t launchIndex); + typedef int (*RunScript_t)(); typedef void (*VoidFunc_t)(); ScriptC(Context *); @@ -44,56 +40,58 @@ public: int mVersionMajor; int mVersionMinor; - RunScript_t mScript; + RunScript_t mRoot; VoidFunc_t mInit; - - void ** mSlotPointers[MAX_SCRIPT_BANKS]; }; Program_t mProgram; - ACCscript* mAccScript; + BCCScriptRef mBccScript; + + const Allocation *ptrToAllocation(const void *) const; + + + virtual void Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len); + + virtual uint32_t run(Context *); - virtual void setupScript(); - virtual uint32_t run(Context *, uint32_t launchID); + virtual void runForEach(Context *rsc, + const Allocation * ain, + Allocation * aout, + const void * usr, + 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: + void setupScript(Context *); + void setupGLState(Context *); + Script * setTLS(Script *); }; -class ScriptCState -{ +class ScriptCState { public: ScriptCState(); ~ScriptCState(); - ScriptC *mScript; + char * mScriptText; + size_t mScriptLen; - ObjectBaseRef<const Type> mConstantBufferTypes[MAX_SCRIPT_BANKS]; - String8 mSlotNames[MAX_SCRIPT_BANKS]; - bool mSlotWritable[MAX_SCRIPT_BANKS]; - String8 mInvokableNames[MAX_SCRIPT_BANKS]; - - void clear(); - void runCompiler(Context *rsc, ScriptC *s); - void appendVarDefines(const Context *rsc, String8 *str); - void appendTypes(const Context *rsc, String8 *str); + bool runCompiler(Context *rsc, ScriptC *s, const char *resName, const char *cacheDir); struct SymbolTable_t { const char * mName; void * mPtr; - const char * mRet; - const char * mParam; + bool threadable; }; - static SymbolTable_t gSyms[]; static const SymbolTable_t * lookupSymbol(const char *); - static void appendDecls(String8 *str); - - KeyedVector<String8,int> mInt32Defines; - KeyedVector<String8,float> mFloatDefines; + static const SymbolTable_t * lookupSymbolCL(const char *); + static const SymbolTable_t * lookupSymbolGL(const char *); }; } } #endif - - - diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp index 202ca3d..8a85f6e 100644 --- a/libs/rs/rsScriptC_Lib.cpp +++ b/libs/rs/rsScriptC_Lib.cpp @@ -17,18 +17,9 @@ #include "rsContext.h" #include "rsScriptC.h" #include "rsMatrix.h" -#include "rsNoise.h" -#include "acc/acc.h" #include "utils/Timers.h" -#define GL_GLEXT_PROTOTYPES - -#include <GLES/gl.h> -#include <GLES/glext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - #include <time.h> using namespace android; @@ -39,254 +30,12 @@ using namespace android::renderscript; Context * rsc = tls->mContext; \ ScriptC * sc = (ScriptC *) tls->mScript -typedef struct { - float x; - float y; - float z; -} vec3_t; - -typedef struct { - float x; - float y; - float z; - float w; -} vec4_t; - -typedef struct { - float x; - float y; -} vec2_t; - -////////////////////////////////////////////////////////////////////////////// -// IO routines -////////////////////////////////////////////////////////////////////////////// - -static float SC_loadF(uint32_t bank, uint32_t offset) -{ - GET_TLS(); - const void *vp = sc->mSlots[bank]->getPtr(); - const float *f = static_cast<const float *>(vp); - //LOGE("loadF %i %i = %f %x", bank, offset, f, ((int *)&f)[0]); - return f[offset]; -} - -static int32_t SC_loadI32(uint32_t bank, uint32_t offset) -{ - GET_TLS(); - const void *vp = sc->mSlots[bank]->getPtr(); - const int32_t *i = static_cast<const int32_t *>(vp); - //LOGE("loadI32 %i %i = %i", bank, offset, t); - return i[offset]; -} - -static float* SC_loadArrayF(uint32_t bank, uint32_t offset) -{ - GET_TLS(); - void *vp = sc->mSlots[bank]->getPtr(); - float *f = static_cast<float *>(vp); - return f + offset; -} - -static int32_t* SC_loadArrayI32(uint32_t bank, uint32_t offset) -{ - GET_TLS(); - void *vp = sc->mSlots[bank]->getPtr(); - int32_t *i = static_cast<int32_t *>(vp); - return i + offset; -} - -static float* SC_loadSimpleMeshVerticesF(RsSimpleMesh mesh, uint32_t idx) -{ - SimpleMesh *tm = static_cast<SimpleMesh *>(mesh); - void *vp = tm->mVertexBuffers[idx]->getPtr();; - return static_cast<float *>(vp); -} - -static void SC_updateSimpleMesh(RsSimpleMesh mesh) -{ - GET_TLS(); - SimpleMesh *sm = static_cast<SimpleMesh *>(mesh); - sm->uploadAll(rsc); -} - -static uint32_t SC_loadU32(uint32_t bank, uint32_t offset) -{ - GET_TLS(); - const void *vp = sc->mSlots[bank]->getPtr(); - const uint32_t *i = static_cast<const uint32_t *>(vp); - return i[offset]; -} - -static void SC_loadVec4(uint32_t bank, uint32_t offset, rsc_Vector4 *v) -{ - GET_TLS(); - const void *vp = sc->mSlots[bank]->getPtr(); - const float *f = static_cast<const float *>(vp); - memcpy(v, &f[offset], sizeof(rsc_Vector4)); -} - -static void SC_loadMatrix(uint32_t bank, uint32_t offset, rsc_Matrix *m) -{ - GET_TLS(); - const void *vp = sc->mSlots[bank]->getPtr(); - const float *f = static_cast<const float *>(vp); - memcpy(m, &f[offset], sizeof(rsc_Matrix)); -} - - -static void SC_storeF(uint32_t bank, uint32_t offset, float v) -{ - //LOGE("storeF %i %i %f", bank, offset, v); - GET_TLS(); - void *vp = sc->mSlots[bank]->getPtr(); - float *f = static_cast<float *>(vp); - f[offset] = v; -} - -static void SC_storeI32(uint32_t bank, uint32_t offset, int32_t v) -{ - GET_TLS(); - void *vp = sc->mSlots[bank]->getPtr(); - int32_t *f = static_cast<int32_t *>(vp); - static_cast<int32_t *>(sc->mSlots[bank]->getPtr())[offset] = v; -} - -static void SC_storeU32(uint32_t bank, uint32_t offset, uint32_t v) -{ - GET_TLS(); - void *vp = sc->mSlots[bank]->getPtr(); - uint32_t *f = static_cast<uint32_t *>(vp); - static_cast<uint32_t *>(sc->mSlots[bank]->getPtr())[offset] = v; -} - -static void SC_storeVec4(uint32_t bank, uint32_t offset, const rsc_Vector4 *v) -{ - GET_TLS(); - void *vp = sc->mSlots[bank]->getPtr(); - float *f = static_cast<float *>(vp); - memcpy(&f[offset], v, sizeof(rsc_Vector4)); -} - -static void SC_storeMatrix(uint32_t bank, uint32_t offset, const rsc_Matrix *m) -{ - GET_TLS(); - void *vp = sc->mSlots[bank]->getPtr(); - float *f = static_cast<float *>(vp); - memcpy(&f[offset], m, sizeof(rsc_Matrix)); -} - -////////////////////////////////////////////////////////////////////////////// -// Vec3 routines -////////////////////////////////////////////////////////////////////////////// - -static void SC_vec3Norm(vec3_t *v) -{ - float len = sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); - len = 1 / len; - v->x *= len; - v->y *= len; - v->z *= len; -} - -static float SC_vec3Length(const vec3_t *v) -{ - return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); -} - -static void SC_vec3Add(vec3_t *dest, const vec3_t *lhs, const vec3_t *rhs) -{ - dest->x = lhs->x + rhs->x; - dest->y = lhs->y + rhs->y; - dest->z = lhs->z + rhs->z; -} - -static void SC_vec3Sub(vec3_t *dest, const vec3_t *lhs, const vec3_t *rhs) -{ - dest->x = lhs->x - rhs->x; - dest->y = lhs->y - rhs->y; - dest->z = lhs->z - rhs->z; -} - -static void SC_vec3Cross(vec3_t *dest, const vec3_t *lhs, const vec3_t *rhs) -{ - float x = lhs->y * rhs->z - lhs->z * rhs->y; - float y = lhs->z * rhs->x - lhs->x * rhs->z; - float z = lhs->x * rhs->y - lhs->y * rhs->x; - dest->x = x; - dest->y = y; - dest->z = z; -} - -static float SC_vec3Dot(const vec3_t *lhs, const vec3_t *rhs) -{ - return lhs->x * rhs->x + lhs->y * rhs->y + lhs->z * rhs->z; -} - -static void SC_vec3Scale(vec3_t *lhs, float scale) -{ - lhs->x *= scale; - lhs->y *= scale; - lhs->z *= scale; -} - -////////////////////////////////////////////////////////////////////////////// -// Vec4 routines -////////////////////////////////////////////////////////////////////////////// - -static void SC_vec4Norm(vec4_t *v) -{ - float len = sqrtf(v->x * v->x + v->y * v->y + v->z * v->z + v->w * v->w); - len = 1 / len; - v->x *= len; - v->y *= len; - v->z *= len; - v->w *= len; -} - -static float SC_vec4Length(const vec4_t *v) -{ - return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z + v->w * v->w); -} - -static void SC_vec4Add(vec4_t *dest, const vec4_t *lhs, const vec4_t *rhs) -{ - dest->x = lhs->x + rhs->x; - dest->y = lhs->y + rhs->y; - dest->z = lhs->z + rhs->z; - dest->w = lhs->w + rhs->w; -} - -static void SC_vec4Sub(vec4_t *dest, const vec4_t *lhs, const vec4_t *rhs) -{ - dest->x = lhs->x - rhs->x; - dest->y = lhs->y - rhs->y; - dest->z = lhs->z - rhs->z; - dest->w = lhs->w - rhs->w; -} - -static float SC_vec4Dot(const vec4_t *lhs, const vec4_t *rhs) -{ - return lhs->x * rhs->x + lhs->y * rhs->y + lhs->z * rhs->z + lhs->w * rhs->w; -} - -static void SC_vec4Scale(vec4_t *lhs, float scale) -{ - lhs->x *= scale; - lhs->y *= scale; - lhs->z *= scale; - lhs->w *= scale; -} ////////////////////////////////////////////////////////////////////////////// // Math routines ////////////////////////////////////////////////////////////////////////////// -#define PI 3.1415926f -#define DEG_TO_RAD PI / 180.0f -#define RAD_TO_DEG 180.0f / PI - -static float SC_sinf_fast(float x) -{ +static float SC_sinf_fast(float x) { const float A = 1.0f / (2.0f * M_PI); const float B = -16.0f; const float C = 8.0f; @@ -303,8 +52,7 @@ static float SC_sinf_fast(float x) return 0.2215f * (y * fabsf(y) - y) + y; } -static float SC_cosf_fast(float x) -{ +static float SC_cosf_fast(float x) { x += float(M_PI / 2); const float A = 1.0f / (2.0f * M_PI); @@ -323,756 +71,762 @@ static float SC_cosf_fast(float x) return 0.2215f * (y * fabsf(y) - y) + y; } -static float SC_randf(float max) -{ +static float SC_randf(float max) { float r = (float)rand(); - return r / RAND_MAX * max; + r *= max; + return r / RAND_MAX; } -static float SC_randf2(float min, float max) -{ +static float SC_randf2(float min, float max) { float r = (float)rand(); - return r / RAND_MAX * (max - min) + min; + r = r * (max - min) + min; + return r / RAND_MAX; } -static int SC_sign(int value) -{ - return (value > 0) - (value < 0); +static int SC_randi(int max) { + return (int)SC_randf(max); } -static float SC_signf(float value) -{ - return (value > 0) - (value < 0); +static int SC_randi2(int min, int max) { + return (int)SC_randf2(min, max); } -static float SC_clampf(float amount, float low, float high) -{ - return amount < low ? low : (amount > high ? high : amount); +static float SC_frac(float v) { + int i = (int)floor(v); + return fmin(v - i, 0x1.fffffep-1f); } -static int SC_clamp(int amount, int low, int high) -{ - return amount < low ? low : (amount > high ? high : amount); -} +////////////////////////////////////////////////////////////////////////////// +// Time routines +////////////////////////////////////////////////////////////////////////////// -static float SC_maxf(float a, float b) -{ - return a > b ? a : b; +static time_t SC_time(time_t *timer) { + GET_TLS(); + return time(timer); } -static float SC_minf(float a, float b) -{ - return a < b ? a : b; -} +static tm* SC_localtime(tm *local, time_t *timer) { + GET_TLS(); + if (!local) { + return NULL; + } -static float SC_sqrf(float v) -{ - return v * v; + // The native localtime function is not thread-safe, so we + // have to apply locking for proper behavior in RenderScript. + pthread_mutex_lock(&rsc->gLibMutex); + tm *tmp = localtime(timer); + memcpy(local, tmp, sizeof(*tmp)); + pthread_mutex_unlock(&rsc->gLibMutex); + return local; } -static int SC_sqr(int v) -{ - return v * v; +static int64_t SC_uptimeMillis() { + return nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); } -static float SC_fracf(float v) -{ - return v - floorf(v); +static int64_t SC_uptimeNanos() { + return systemTime(SYSTEM_TIME_MONOTONIC); } -static float SC_roundf(float v) -{ - return floorf(v + 0.4999999999); +static float SC_getDt() { + GET_TLS(); + int64_t l = sc->mEnviroment.mLastDtTime; + sc->mEnviroment.mLastDtTime = systemTime(SYSTEM_TIME_MONOTONIC); + return ((float)(sc->mEnviroment.mLastDtTime - l)) / 1.0e9; } -static float SC_distf2(float x1, float y1, float x2, float y2) -{ - float x = x2 - x1; - float y = y2 - y1; - return sqrtf(x * x + y * y); -} +////////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////////// -static float SC_distf3(float x1, float y1, float z1, float x2, float y2, float z2) -{ - float x = x2 - x1; - float y = y2 - y1; - float z = z2 - z1; - return sqrtf(x * x + y * y + z * z); +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 float SC_magf2(float a, float b) -{ - return sqrtf(a * a + b * b); +static uint32_t SC_allocGetDimY(RsAllocation va) { + const Allocation *a = static_cast<const Allocation *>(va); + CHECK_OBJ(a); + return a->getType()->getDimY(); } -static float SC_magf3(float a, float b, float c) -{ - return sqrtf(a * a + b * b + c * c); +static uint32_t SC_allocGetDimZ(RsAllocation va) { + const Allocation *a = static_cast<const Allocation *>(va); + CHECK_OBJ(a); + return a->getType()->getDimZ(); } -static float SC_radf(float degrees) -{ - return degrees * DEG_TO_RAD; +static uint32_t SC_allocGetDimLOD(RsAllocation va) { + const Allocation *a = static_cast<const Allocation *>(va); + CHECK_OBJ(a); + return a->getType()->getDimLOD(); } -static float SC_degf(float radians) -{ - return radians * RAD_TO_DEG; +static uint32_t SC_allocGetDimFaces(RsAllocation va) { + const Allocation *a = static_cast<const Allocation *>(va); + CHECK_OBJ(a); + return a->getType()->getDimFaces(); } -static float SC_lerpf(float start, float stop, float amount) -{ - return start + (stop - start) * amount; +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 float SC_normf(float start, float stop, float value) -{ - return (value - start) / (stop - start); +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 float SC_mapf(float minStart, float minStop, float maxStart, float maxStop, float value) -{ - return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart)); +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())]; } -////////////////////////////////////////////////////////////////////////////// -// Time routines -////////////////////////////////////////////////////////////////////////////// - -static int32_t SC_second() -{ - GET_TLS(); - - time_t rawtime; - time(&rawtime); - - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_sec; +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(); + } + if (vdst[0]) { + CHECK_OBJ(vdst[0]); + static_cast<ObjectBase *>(vdst[0])->decSysRef(); + } + *vdst = vsrc; + //LOGE("SC_setObject *"); } -static int32_t SC_minute() -{ - GET_TLS(); - - time_t rawtime; - time(&rawtime); - - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_min; +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(); + } + *vdst = NULL; + //LOGE("SC_clearObject *"); } -static int32_t SC_hour() -{ - GET_TLS(); - - time_t rawtime; - time(&rawtime); - - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_hour; +static bool SC_isObject(RsAllocation vsrc) { + return vsrc != NULL; } -static int32_t SC_day() -{ - GET_TLS(); - - time_t rawtime; - time(&rawtime); - - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_mday; +static void SC_debugF(const char *s, float f) { + LOGD("%s %f, 0x%08x", s, f, *((int *) (&f))); } - -static int32_t SC_month() -{ - GET_TLS(); - - time_t rawtime; - time(&rawtime); - - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_mon; +static void SC_debugFv2(const char *s, float f1, float f2) { + LOGD("%s {%f, %f}", s, f1, f2); } - -static int32_t SC_year() -{ - GET_TLS(); - - time_t rawtime; - time(&rawtime); - - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_year; +static void SC_debugFv3(const char *s, float f1, float f2, float f3) { + LOGD("%s {%f, %f, %f}", s, f1, f2, f3); } - -static int32_t SC_uptimeMillis() -{ - return nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); +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 int32_t SC_startTimeMillis() -{ - GET_TLS(); - return sc->mEnviroment.mStartTimeMillis; +static void SC_debugD(const char *s, double d) { + LOGD("%s %f, 0x%08llx", s, d, *((long long *) (&d))); } - -static int32_t SC_elapsedTimeMillis() -{ - GET_TLS(); - return nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)) - - sc->mEnviroment.mStartTimeMillis; +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]); } - -////////////////////////////////////////////////////////////////////////////// -// Matrix routines -////////////////////////////////////////////////////////////////////////////// - - -static void SC_matrixLoadIdentity(rsc_Matrix *mat) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->loadIdentity(); +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_matrixLoadFloat(rsc_Matrix *mat, const float *f) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->load(f); +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_matrixLoadMat(rsc_Matrix *mat, const rsc_Matrix *newmat) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->load(reinterpret_cast<const Matrix *>(newmat)); +static void SC_debugI32(const char *s, int32_t i) { + LOGD("%s %i 0x%x", s, i, i); } - -static void SC_matrixLoadRotate(rsc_Matrix *mat, float rot, float x, float y, float z) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->loadRotate(rot, x, y, z); +static void SC_debugU32(const char *s, uint32_t i) { + LOGD("%s %u 0x%x", s, i, i); } - -static void SC_matrixLoadScale(rsc_Matrix *mat, float x, float y, float z) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->loadScale(x, y, z); +static void SC_debugLL64(const char *s, long long ll) { + LOGD("%s %lld 0x%llx", s, ll, ll); } - -static void SC_matrixLoadTranslate(rsc_Matrix *mat, float x, float y, float z) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->loadTranslate(x, y, z); +static void SC_debugULL64(const char *s, unsigned long long ll) { + LOGD("%s %llu 0x%llx", s, ll, ll); } -static void SC_matrixLoadMultiply(rsc_Matrix *mat, const rsc_Matrix *lhs, const rsc_Matrix *rhs) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->loadMultiply(reinterpret_cast<const Matrix *>(lhs), - reinterpret_cast<const Matrix *>(rhs)); +static void SC_debugP(const char *s, const void *p) { + LOGD("%s %p", s, p); } -static void SC_matrixMultiply(rsc_Matrix *mat, const rsc_Matrix *rhs) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->multiply(reinterpret_cast<const Matrix *>(rhs)); +static uint32_t SC_toClient2(int cmdID, void *data, int len) { + GET_TLS(); + //LOGE("SC_toClient %i %i %i", cmdID, len); + return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, false); } -static void SC_matrixRotate(rsc_Matrix *mat, float rot, float x, float y, float z) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->rotate(rot, x, y, z); +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 void SC_matrixScale(rsc_Matrix *mat, float x, float y, float z) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->scale(x, y, z); +static uint32_t SC_toClientBlocking2(int cmdID, void *data, int len) { + GET_TLS(); + //LOGE("SC_toClientBlocking %i %i", cmdID, len); + return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, true); } -static void SC_matrixTranslate(rsc_Matrix *mat, float x, float y, float z) -{ - Matrix *m = reinterpret_cast<Matrix *>(mat); - m->translate(x, y, z); +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); } - -static void SC_vec2Rand(float *vec, float maxLen) -{ - float angle = SC_randf(PI * 2); - float len = SC_randf(maxLen); - vec[0] = len * sinf(angle); - vec[1] = len * cosf(angle); +int SC_divsi3(int a, int b) { + return a / b; } - - -////////////////////////////////////////////////////////////////////////////// -// Context -////////////////////////////////////////////////////////////////////////////// - -static void SC_bindTexture(RsProgramFragment vpf, uint32_t slot, RsAllocation va) -{ - GET_TLS(); - rsi_ProgramBindTexture(rsc, - static_cast<ProgramFragment *>(vpf), - slot, - static_cast<Allocation *>(va)); - +int SC_modsi3(int a, int b) { + return a % b; } -static void SC_bindSampler(RsProgramFragment vpf, uint32_t slot, RsSampler vs) -{ - GET_TLS(); - rsi_ProgramBindSampler(rsc, - static_cast<ProgramFragment *>(vpf), - slot, - static_cast<Sampler *>(vs)); - +unsigned int SC_udivsi3(unsigned int a, unsigned int b) { + return a / b; } -static void SC_bindProgramFragmentStore(RsProgramFragmentStore pfs) -{ - GET_TLS(); - rsi_ContextBindProgramFragmentStore(rsc, pfs); - +unsigned int SC_umodsi3(unsigned int a, unsigned int b) { + return a % b; } -static void SC_bindProgramFragment(RsProgramFragment pf) -{ +int SC_getAllocation(const void *ptr) { GET_TLS(); - rsi_ContextBindProgramFragment(rsc, pf); - + const Allocation *alloc = sc->ptrToAllocation(ptr); + return (int)alloc; } -static void SC_bindProgramVertex(RsProgramVertex pv) -{ - GET_TLS(); - rsi_ContextBindProgramVertex(rsc, pv); - +void SC_allocationMarkDirty(RsAllocation a) { + Allocation *alloc = static_cast<Allocation *>(a); + alloc->sendDirty(); } -////////////////////////////////////////////////////////////////////////////// -// VP -////////////////////////////////////////////////////////////////////////////// - -static void SC_vpLoadModelMatrix(const rsc_Matrix *m) -{ +void SC_ForEach(RsScript vs, + RsAllocation vin, + RsAllocation vout, + const void *usr) { GET_TLS(); - rsc->getVertex()->setModelviewMatrix(m); + 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); } -static void SC_vpLoadTextureMatrix(const rsc_Matrix *m) -{ +void SC_ForEach2(RsScript vs, + RsAllocation vin, + RsAllocation vout, + const void *usr, + const RsScriptCall *call) { GET_TLS(); - rsc->getVertex()->setTextureMatrix(m); + 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); } - ////////////////////////////////////////////////////////////////////////////// -// Drawing +// Heavy math functions ////////////////////////////////////////////////////////////////////////////// -static void SC_drawLine(float x1, float y1, float z1, - float x2, float y2, float z2) -{ - GET_TLS(); - if (!rsc->setupCheck()) { - return; - } - - float vtx[] = { x1, y1, z1, x2, y2, z2 }; - VertexArray va; - va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx); - if (rsc->checkVersion2_0()) { - va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache); - } else { - va.setupGL(rsc, &rsc->mStateVertexArray); - } +typedef struct { + float m[16]; +} rs_matrix4x4; - glDrawArrays(GL_LINES, 0, 2); -} +typedef struct { + float m[9]; +} rs_matrix3x3; -static void SC_drawPoint(float x, float y, float z) -{ - GET_TLS(); - if (!rsc->setupCheck()) { - return; +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; } - - float vtx[] = { x, y, z }; - - VertexArray va; - va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx); - if (rsc->checkVersion2_0()) { - va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache); - } else { - va.setupGL(rsc, &rsc->mStateVertexArray); + 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); } - - glDrawArrays(GL_POINTS, 0, 1); } -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(); - if (!rsc->setupCheck()) { - return; - } - - //LOGE("Quad"); - //LOGE("%4.2f, %4.2f, %4.2f", x1, y1, z1); - //LOGE("%4.2f, %4.2f, %4.2f", x2, y2, z2); - //LOGE("%4.2f, %4.2f, %4.2f", x3, y3, z3); - //LOGE("%4.2f, %4.2f, %4.2f", x4, y4, z4); - - 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 va; - va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx); - va.addLegacy(GL_FLOAT, 2, 8, RS_KIND_TEXTURE, false, (uint32_t)tex); - if (rsc->checkVersion2_0()) { - va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache); - } else { - va.setupGL(rsc, &rsc->mStateVertexArray); - } - - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +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_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); +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_drawSpriteScreenspace(float x, float y, float z, float w, float h) -{ - GET_TLS(); - ObjectBaseRef<const ProgramVertex> tmp(rsc->getVertex()); - rsc->setVertex(rsc->getDefaultProgramVertex()); - //rsc->setupCheck(); - - //GLint crop[4] = {0, h, w, -h}; - - float sh = rsc->getHeight(); - - SC_drawQuad(x, sh - y, z, - x+w, sh - y, z, - x+w, sh - (y+h), z, - x, sh - (y+h), z); - rsc->setVertex((ProgramVertex *)tmp.get()); +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_drawSpriteScreenspaceCropped(float x, float y, float z, float w, float h, - float cx0, float cy0, float cx1, float cy1) -{ - GET_TLS(); - if (!rsc->setupCheck()) { - return; +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); } - - GLint crop[4] = {cx0, cy0, cx1, cy1}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - glDrawTexfOES(x, y, z, w, h); } -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]); +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); +} - // U, V, W, H - SC_drawSpriteScreenspace(vout[0], vout[1], z, h, w); - //rsc->setupCheck(); +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); +} -static void SC_drawRect(float x1, float y1, - float x2, float y2, float z) -{ - SC_drawQuad(x1, y2, z, - x2, y2, z, - x2, y1, z, - x1, y1, z); +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_drawSimpleMesh(RsSimpleMesh vsm) -{ - GET_TLS(); - SimpleMesh *sm = static_cast<SimpleMesh *>(vsm); - if (!rsc->setupCheck()) { - return; - } - sm->render(rsc); +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_drawSimpleMeshRange(RsSimpleMesh vsm, uint32_t start, uint32_t len) -{ - GET_TLS(); - SimpleMesh *sm = static_cast<SimpleMesh *>(vsm); - if (!rsc->setupCheck()) { - return; - } - sm->renderRange(rsc, start, len); +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); +} -////////////////////////////////////////////////////////////////////////////// -// -////////////////////////////////////////////////////////////////////////////// -static void SC_color(float r, float g, float b, float a) -{ - GET_TLS(); - rsc->mStateVertex.color[0] = r; - rsc->mStateVertex.color[1] = g; - rsc->mStateVertex.color[2] = b; - rsc->mStateVertex.color[3] = a; - if (!rsc->checkVersion2_0()) { - glColor4f(r, g, b, a); - } -} +// Returns true if the matrix was successfully inversed +static bool SC_MatrixInverse_4x4(rs_matrix4x4 *m) { + rs_matrix4x4 result; -static void SC_ambient(float r, float g, float b, float a) -{ - GLfloat params[] = { r, g, b, a }; - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, params); -} - -static void SC_diffuse(float r, float g, float b, float a) -{ - GLfloat params[] = { r, g, b, a }; - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, params); -} - -static void SC_specular(float r, float g, float b, float a) -{ - GLfloat params[] = { r, g, b, a }; - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, params); -} - -static void SC_emission(float r, float g, float b, float a) -{ - GLfloat params[] = { r, g, b, a }; - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, params); -} - -static void SC_shininess(float s) -{ - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, s); -} - -static void SC_pointAttenuation(float a, float b, float c) -{ - GLfloat params[] = { a, b, c }; - glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, params); -} - -static void SC_hsbToRgb(float h, float s, float b, float* rgb) -{ - float red = 0.0f; - float green = 0.0f; - float blue = 0.0f; - - float x = h; - float y = s; - float z = b; - - float hf = (x - (int) x) * 6.0f; - int ihf = (int) hf; - float f = hf - ihf; - float pv = z * (1.0f - y); - float qv = z * (1.0f - y * f); - float tv = z * (1.0f - y * (1.0f - f)); - - switch (ihf) { - case 0: // Red is the dominant color - red = z; - green = tv; - blue = pv; - break; - case 1: // Green is the dominant color - red = qv; - green = z; - blue = pv; - break; - case 2: - red = pv; - green = z; - blue = tv; - break; - case 3: // Blue is the dominant color - red = pv; - green = qv; - blue = z; - break; - case 4: - red = tv; - green = pv; - blue = z; - break; - case 5: // Red is the dominant color - red = z; - green = pv; - blue = qv; - break; - } + 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; - rgb[0] = red; - rgb[1] = green; - rgb[2] = blue; -} + 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])); -static int SC_hsbToAbgr(float h, float s, float b, float a) -{ - float rgb[3]; - SC_hsbToRgb(h, s, b, rgb); - return int(a * 255.0f) << 24 | - int(rgb[2] * 255.0f) << 16 | - int(rgb[1] * 255.0f) << 8 | - int(rgb[0] * 255.0f); -} + float cofactor = (i+j) & 1 ? -minor : minor; -static void SC_hsb(float h, float s, float b, float a) -{ - GET_TLS(); - float rgb[3]; - SC_hsbToRgb(h, s, b, rgb); - if (rsc->checkVersion2_0()) { - glVertexAttrib4f(1, rgb[0], rgb[1], rgb[2], a); - } else { - glColor4f(rgb[0], rgb[1], rgb[2], a); + result.m[4*i + j] = cofactor; + } } -} -static void SC_uploadToTexture(RsAllocation va, uint32_t baseMipLevel) -{ - GET_TLS(); - rsi_AllocationUploadToTexture(rsc, va, false, baseMipLevel); -} + // 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]; -static void SC_uploadToBufferObject(RsAllocation va) -{ - GET_TLS(); - rsi_AllocationUploadToBufferObject(rsc, va); -} + if (fabs(det) < 1e-6) { + return false; + } -static void SC_syncToGL(RsAllocation va) -{ - GET_TLS(); - Allocation *a = static_cast<Allocation *>(va); + det = 1.0f / det; + for (i = 0; i < 16; ++i) { + m->m[i] = result.m[i] * det; + } + return true; } -static void SC_ClearColor(float r, float g, float b, float a) -{ - //LOGE("c %f %f %f %f", r, g, b, a); - GET_TLS(); - sc->mEnviroment.mClearColor[0] = r; - sc->mEnviroment.mClearColor[1] = g; - sc->mEnviroment.mClearColor[2] = b; - sc->mEnviroment.mClearColor[3] = a; -} +// Returns true if the matrix was successfully inversed +static bool SC_MatrixInverseTranspose_4x4(rs_matrix4x4 *m) { + rs_matrix4x4 result; -static void SC_debugF(const char *s, float f) -{ - LOGE("%s %f", s, f); -} + 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; -static void SC_debugHexF(const char *s, float f) -{ - LOGE("%s 0x%x", s, *((int *) (&f))); -} + 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])); -static void SC_debugI32(const char *s, int32_t i) -{ - LOGE("%s %i", s, i); -} + float cofactor = (i+j) & 1 ? -minor : minor; -static void SC_debugHexI32(const char *s, int32_t i) -{ - LOGE("%s 0x%x", s, i); -} + result.m[4*j + i] = cofactor; + } + } -static uint32_t SC_getWidth() -{ - GET_TLS(); - return rsc->getWidth(); -} + // 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]; -static uint32_t SC_getHeight() -{ - GET_TLS(); - return rsc->getHeight(); -} + if (fabs(det) < 1e-6) { + return false; + } + + det = 1.0f / det; + for (i = 0; i < 16; ++i) { + m->m[i] = result.m[i] * det; + } -static uint32_t SC_colorFloatRGBAtoUNorm8(float r, float g, float b, float a) -{ - uint32_t c = 0; - c |= (uint32_t)(r * 255.f + 0.5f); - c |= ((uint32_t)(g * 255.f + 0.5f)) << 8; - c |= ((uint32_t)(b * 255.f + 0.5f)) << 16; - c |= ((uint32_t)(a * 255.f + 0.5f)) << 24; - return c; + return true; } -static uint32_t SC_colorFloatRGBAto565(float r, float g, float b) -{ - uint32_t ir = (uint32_t)(r * 255.f + 0.5f); - uint32_t ig = (uint32_t)(g * 255.f + 0.5f); - uint32_t ib = (uint32_t)(b * 255.f + 0.5f); - return rs888to565(ir, ig, ib); +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; + } + } } -static uint32_t SC_toClient(void *data, int cmdID, int len, int waitForSpace) -{ - GET_TLS(); - return rsc->sendMessageToClient(data, cmdID, len, waitForSpace != 0); +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_scriptCall(int scriptID) -{ - GET_TLS(); - rsc->runScript((Script *)scriptID, 0); +static void SC_MatrixTranspose_2x2(rs_matrix2x2 *m) { + float temp = m->m[1]; + m->m[1] = m->m[2]; + m->m[2] = temp; } @@ -1080,315 +834,179 @@ static void SC_scriptCall(int scriptID) // Class implementation ////////////////////////////////////////////////////////////////////////////// -ScriptCState::SymbolTable_t ScriptCState::gSyms[] = { - // IO - { "loadI32", (void *)&SC_loadI32, - "int", "(int, int)" }, - //{ "loadU32", (void *)&SC_loadU32, "unsigned int", "(int, int)" }, - { "loadF", (void *)&SC_loadF, - "float", "(int, int)" }, - { "loadArrayF", (void *)&SC_loadArrayF, - "float*", "(int, int)" }, - { "loadArrayI32", (void *)&SC_loadArrayI32, - "int*", "(int, int)" }, - { "loadVec4", (void *)&SC_loadVec4, - "void", "(int, int, float *)" }, - { "loadMatrix", (void *)&SC_loadMatrix, - "void", "(int, int, float *)" }, - { "storeI32", (void *)&SC_storeI32, - "void", "(int, int, int)" }, - //{ "storeU32", (void *)&SC_storeU32, "void", "(int, int, unsigned int)" }, - { "storeF", (void *)&SC_storeF, - "void", "(int, int, float)" }, - { "storeVec4", (void *)&SC_storeVec4, - "void", "(int, int, float *)" }, - { "storeMatrix", (void *)&SC_storeMatrix, - "void", "(int, int, float *)" }, - { "loadSimpleMeshVerticesF", (void *)&SC_loadSimpleMeshVerticesF, - "float*", "(int, int)" }, - { "updateSimpleMesh", (void *)&SC_updateSimpleMesh, - "void", "(int)" }, - - // math - { "modf", (void *)&fmod, - "float", "(float, float)" }, - { "abs", (void *)&abs, - "int", "(int)" }, - { "absf", (void *)&fabsf, - "float", "(float)" }, - { "sinf_fast", (void *)&SC_sinf_fast, - "float", "(float)" }, - { "cosf_fast", (void *)&SC_cosf_fast, - "float", "(float)" }, - { "sinf", (void *)&sinf, - "float", "(float)" }, - { "cosf", (void *)&cosf, - "float", "(float)" }, - { "asinf", (void *)&asinf, - "float", "(float)" }, - { "acosf", (void *)&acosf, - "float", "(float)" }, - { "atanf", (void *)&atanf, - "float", "(float)" }, - { "atan2f", (void *)&atan2f, - "float", "(float, float)" }, - { "fabsf", (void *)&fabsf, - "float", "(float)" }, - { "randf", (void *)&SC_randf, - "float", "(float)" }, - { "randf2", (void *)&SC_randf2, - "float", "(float, float)" }, - { "floorf", (void *)&floorf, - "float", "(float)" }, - { "fracf", (void *)&SC_fracf, - "float", "(float)" }, - { "ceilf", (void *)&ceilf, - "float", "(float)" }, - { "roundf", (void *)&SC_roundf, - "float", "(float)" }, - { "expf", (void *)&expf, - "float", "(float)" }, - { "logf", (void *)&logf, - "float", "(float)" }, - { "powf", (void *)&powf, - "float", "(float, float)" }, - { "maxf", (void *)&SC_maxf, - "float", "(float, float)" }, - { "minf", (void *)&SC_minf, - "float", "(float, float)" }, - { "sqrt", (void *)&sqrt, - "int", "(int)" }, - { "sqrtf", (void *)&sqrtf, - "float", "(float)" }, - { "sqr", (void *)&SC_sqr, - "int", "(int)" }, - { "sqrf", (void *)&SC_sqrf, - "float", "(float)" }, - { "sign", (void *)&SC_sign, - "int", "(int)" }, - { "signf", (void *)&SC_signf, - "float", "(float)" }, - { "clamp", (void *)&SC_clamp, - "int", "(int, int, int)" }, - { "clampf", (void *)&SC_clampf, - "float", "(float, float, float)" }, - { "distf2", (void *)&SC_distf2, - "float", "(float, float, float, float)" }, - { "distf3", (void *)&SC_distf3, - "float", "(float, float, float, float, float, float)" }, - { "magf2", (void *)&SC_magf2, - "float", "(float, float)" }, - { "magf3", (void *)&SC_magf3, - "float", "(float, float, float)" }, - { "radf", (void *)&SC_radf, - "float", "(float)" }, - { "degf", (void *)&SC_degf, - "float", "(float)" }, - { "lerpf", (void *)&SC_lerpf, - "float", "(float, float, float)" }, - { "normf", (void *)&SC_normf, - "float", "(float, float, float)" }, - { "mapf", (void *)&SC_mapf, - "float", "(float, float, float, float, float)" }, - { "noisef", (void *)&SC_noisef, - "float", "(float)" }, - { "noisef2", (void *)&SC_noisef2, - "float", "(float, float)" }, - { "noisef3", (void *)&SC_noisef3, - "float", "(float, float, float)" }, - { "turbulencef2", (void *)&SC_turbulencef2, - "float", "(float, float, float)" }, - { "turbulencef3", (void *)&SC_turbulencef3, - "float", "(float, float, float, float)" }, +// 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 }, + + // 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 - { "second", (void *)&SC_second, - "int", "()" }, - { "minute", (void *)&SC_minute, - "int", "()" }, - { "hour", (void *)&SC_hour, - "int", "()" }, - { "day", (void *)&SC_day, - "int", "()" }, - { "month", (void *)&SC_month, - "int", "()" }, - { "year", (void *)&SC_year, - "int", "()" }, - { "uptimeMillis", (void*)&SC_uptimeMillis, - "int", "()" }, // TODO: use long instead - { "startTimeMillis", (void*)&SC_startTimeMillis, - "int", "()" }, // TODO: use long instead - { "elapsedTimeMillis", (void*)&SC_elapsedTimeMillis, - "int", "()" }, // TODO: use long instead + { "_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 - { "matrixLoadIdentity", (void *)&SC_matrixLoadIdentity, - "void", "(float *mat)" }, - { "matrixLoadFloat", (void *)&SC_matrixLoadFloat, - "void", "(float *mat, float *f)" }, - { "matrixLoadMat", (void *)&SC_matrixLoadMat, - "void", "(float *mat, float *newmat)" }, - { "matrixLoadRotate", (void *)&SC_matrixLoadRotate, - "void", "(float *mat, float rot, float x, float y, float z)" }, - { "matrixLoadScale", (void *)&SC_matrixLoadScale, - "void", "(float *mat, float x, float y, float z)" }, - { "matrixLoadTranslate", (void *)&SC_matrixLoadTranslate, - "void", "(float *mat, float x, float y, float z)" }, - { "matrixLoadMultiply", (void *)&SC_matrixLoadMultiply, - "void", "(float *mat, float *lhs, float *rhs)" }, - { "matrixMultiply", (void *)&SC_matrixMultiply, - "void", "(float *mat, float *rhs)" }, - { "matrixRotate", (void *)&SC_matrixRotate, - "void", "(float *mat, float rot, float x, float y, float z)" }, - { "matrixScale", (void *)&SC_matrixScale, - "void", "(float *mat, float x, float y, float z)" }, - { "matrixTranslate", (void *)&SC_matrixTranslate, - "void", "(float *mat, float x, float y, float z)" }, - - // vector - { "vec2Rand", (void *)&SC_vec2Rand, - "void", "(float *vec, float maxLen)" }, - - // vec3 - { "vec3Norm", (void *)&SC_vec3Norm, - "void", "(struct vecF32_3_s *)" }, - { "vec3Length", (void *)&SC_vec3Length, - "float", "(struct vecF32_3_s *)" }, - { "vec3Add", (void *)&SC_vec3Add, - "void", "(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs)" }, - { "vec3Sub", (void *)&SC_vec3Sub, - "void", "(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs)" }, - { "vec3Cross", (void *)&SC_vec3Cross, - "void", "(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs)" }, - { "vec3Dot", (void *)&SC_vec3Dot, - "float", "(struct vecF32_3_s *lhs, struct vecF32_3_s *rhs)" }, - { "vec3Scale", (void *)&SC_vec3Scale, - "void", "(struct vecF32_3_s *lhs, float scale)" }, - - // vec4 - { "vec4Norm", (void *)&SC_vec4Norm, - "void", "(struct vecF32_4_s *)" }, - { "vec4Length", (void *)&SC_vec4Length, - "float", "(struct vecF32_4_s *)" }, - { "vec4Add", (void *)&SC_vec4Add, - "void", "(struct vecF32_4_s *dest, struct vecF32_4_s *lhs, struct vecF32_4_s *rhs)" }, - { "vec4Sub", (void *)&SC_vec4Sub, - "void", "(struct vecF32_4_s *dest, struct vecF32_4_s *lhs, struct vecF32_4_s *rhs)" }, - { "vec4Dot", (void *)&SC_vec4Dot, - "float", "(struct vecF32_4_s *lhs, struct vecF32_4_s *rhs)" }, - { "vec4Scale", (void *)&SC_vec4Scale, - "void", "(struct vecF32_4_s *lhs, float scale)" }, - - // context - { "bindProgramFragment", (void *)&SC_bindProgramFragment, - "void", "(int)" }, - { "bindProgramFragmentStore", (void *)&SC_bindProgramFragmentStore, - "void", "(int)" }, - { "bindProgramStore", (void *)&SC_bindProgramFragmentStore, - "void", "(int)" }, - { "bindProgramVertex", (void *)&SC_bindProgramVertex, - "void", "(int)" }, - { "bindSampler", (void *)&SC_bindSampler, - "void", "(int, int, int)" }, - { "bindTexture", (void *)&SC_bindTexture, - "void", "(int, int, int)" }, - - // vp - { "vpLoadModelMatrix", (void *)&SC_vpLoadModelMatrix, - "void", "(void *)" }, - { "vpLoadTextureMatrix", (void *)&SC_vpLoadTextureMatrix, - "void", "(void *)" }, - - - - // drawing - { "drawRect", (void *)&SC_drawRect, - "void", "(float x1, float y1, float x2, float y2, float z)" }, - { "drawQuad", (void *)&SC_drawQuad, - "void", "(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4)" }, - { "drawQuadTexCoords", (void *)&SC_drawQuadTexCoords, - "void", "(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)" }, - { "drawSprite", (void *)&SC_drawSprite, - "void", "(float x, float y, float z, float w, float h)" }, - { "drawSpriteScreenspace", (void *)&SC_drawSpriteScreenspace, - "void", "(float x, float y, float z, float w, float h)" }, - { "drawSpriteScreenspaceCropped", (void *)&SC_drawSpriteScreenspaceCropped, - "void", "(float x, float y, float z, float w, float h, float cx0, float cy0, float cx1, float cy1)" }, - { "drawLine", (void *)&SC_drawLine, - "void", "(float x1, float y1, float z1, float x2, float y2, float z2)" }, - { "drawPoint", (void *)&SC_drawPoint, - "void", "(float x1, float y1, float z1)" }, - { "drawSimpleMesh", (void *)&SC_drawSimpleMesh, - "void", "(int ism)" }, - { "drawSimpleMeshRange", (void *)&SC_drawSimpleMeshRange, - "void", "(int ism, int start, int len)" }, - - - // misc - { "pfClearColor", (void *)&SC_ClearColor, - "void", "(float, float, float, float)" }, - { "color", (void *)&SC_color, - "void", "(float, float, float, float)" }, - { "hsb", (void *)&SC_hsb, - "void", "(float, float, float, float)" }, - { "hsbToRgb", (void *)&SC_hsbToRgb, - "void", "(float, float, float, float*)" }, - { "hsbToAbgr", (void *)&SC_hsbToAbgr, - "int", "(float, float, float, float)" }, - { "ambient", (void *)&SC_ambient, - "void", "(float, float, float, float)" }, - { "diffuse", (void *)&SC_diffuse, - "void", "(float, float, float, float)" }, - { "specular", (void *)&SC_specular, - "void", "(float, float, float, float)" }, - { "emission", (void *)&SC_emission, - "void", "(float, float, float, float)" }, - { "shininess", (void *)&SC_shininess, - "void", "(float)" }, - { "pointAttenuation", (void *)&SC_pointAttenuation, - "void", "(float, float, float)" }, - - { "uploadToTexture", (void *)&SC_uploadToTexture, - "void", "(int, int)" }, - { "uploadToBufferObject", (void *)&SC_uploadToBufferObject, - "void", "(int)" }, - - { "syncToGL", (void *)&SC_syncToGL, - "void", "(int)" }, - - { "colorFloatRGBAtoUNorm8", (void *)&SC_colorFloatRGBAtoUNorm8, - "int", "(float, float, float, float)" }, - { "colorFloatRGBto565", (void *)&SC_colorFloatRGBAto565, - "int", "(float, float, float)" }, - - - { "getWidth", (void *)&SC_getWidth, - "int", "()" }, - { "getHeight", (void *)&SC_getHeight, - "int", "()" }, - - { "sendToClient", (void *)&SC_toClient, - "int", "(void *data, int cmdID, int len, int waitForSpace)" }, - - - { "debugF", (void *)&SC_debugF, - "void", "(void *, float)" }, - { "debugI32", (void *)&SC_debugI32, - "void", "(void *, int)" }, - { "debugHexF", (void *)&SC_debugHexF, - "void", "(void *, float)" }, - { "debugHexI32", (void *)&SC_debugHexI32, - "void", "(void *, int)" }, - - { "scriptCall", (void *)&SC_scriptCall, - "void", "(int)" }, - - - { NULL, NULL, NULL, NULL } + { "_Z20rsMatrixLoadIdentityP12rs_matrix4x4", (void *)&SC_MatrixLoadIdentity_4x4, false }, + { "_Z20rsMatrixLoadIdentityP12rs_matrix3x3", (void *)&SC_MatrixLoadIdentity_3x3, false }, + { "_Z20rsMatrixLoadIdentityP12rs_matrix2x2", (void *)&SC_MatrixLoadIdentity_2x2, false }, + + { "_Z12rsMatrixLoadP12rs_matrix4x4PKf", (void *)&SC_MatrixLoad_4x4_f, false }, + { "_Z12rsMatrixLoadP12rs_matrix3x3PKf", (void *)&SC_MatrixLoad_3x3_f, false }, + { "_Z12rsMatrixLoadP12rs_matrix2x2PKf", (void *)&SC_MatrixLoad_2x2_f, false }, + + { "_Z12rsMatrixLoadP12rs_matrix4x4PKS_", (void *)&SC_MatrixLoad_4x4_4x4, false }, + { "_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix3x3", (void *)&SC_MatrixLoad_4x4_3x3, false }, + { "_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix2x2", (void *)&SC_MatrixLoad_4x4_2x2, false }, + { "_Z12rsMatrixLoadP12rs_matrix3x3PKS_", (void *)&SC_MatrixLoad_3x3_3x3, false }, + { "_Z12rsMatrixLoadP12rs_matrix2x2PKS_", (void *)&SC_MatrixLoad_2x2_2x2, false }, + + { "_Z18rsMatrixLoadRotateP12rs_matrix4x4ffff", (void *)&SC_MatrixLoadRotate, false }, + { "_Z17rsMatrixLoadScaleP12rs_matrix4x4fff", (void *)&SC_MatrixLoadScale, false }, + { "_Z21rsMatrixLoadTranslateP12rs_matrix4x4fff", (void *)&SC_MatrixLoadTranslate, false }, + { "_Z14rsMatrixRotateP12rs_matrix4x4ffff", (void *)&SC_MatrixRotate, false }, + { "_Z13rsMatrixScaleP12rs_matrix4x4fff", (void *)&SC_MatrixScale, false }, + { "_Z17rsMatrixTranslateP12rs_matrix4x4fff", (void *)&SC_MatrixTranslate, false }, + + { "_Z20rsMatrixLoadMultiplyP12rs_matrix4x4PKS_S2_", (void *)&SC_MatrixLoadMultiply_4x4_4x4_4x4, false }, + { "_Z16rsMatrixMultiplyP12rs_matrix4x4PKS_", (void *)&SC_MatrixMultiply_4x4_4x4, false }, + { "_Z20rsMatrixLoadMultiplyP12rs_matrix3x3PKS_S2_", (void *)&SC_MatrixLoadMultiply_3x3_3x3_3x3, false }, + { "_Z16rsMatrixMultiplyP12rs_matrix3x3PKS_", (void *)&SC_MatrixMultiply_3x3_3x3, false }, + { "_Z20rsMatrixLoadMultiplyP12rs_matrix2x2PKS_S2_", (void *)&SC_MatrixLoadMultiply_2x2_2x2_2x2, false }, + { "_Z16rsMatrixMultiplyP12rs_matrix2x2PKS_", (void *)&SC_MatrixMultiply_2x2_2x2, false }, + + { "_Z17rsMatrixLoadOrthoP12rs_matrix4x4ffffff", (void *)&SC_MatrixLoadOrtho, false }, + { "_Z19rsMatrixLoadFrustumP12rs_matrix4x4ffffff", (void *)&SC_MatrixLoadFrustum, false }, + { "_Z23rsMatrixLoadPerspectiveP12rs_matrix4x4ffff", (void *)&SC_MatrixLoadPerspective, false }, + + { "_Z15rsMatrixInverseP12rs_matrix4x4", (void *)&SC_MatrixInverse_4x4, false }, + { "_Z24rsMatrixInverseTransposeP12rs_matrix4x4", (void *)&SC_MatrixInverseTranspose_4x4, false }, + { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_4x4, false }, + { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_3x3, false }, + { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_2x2, false }, + + { "_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) -{ +const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym) { ScriptCState::SymbolTable_t *syms = gSyms; while (syms->mPtr) { @@ -1399,18 +1017,3 @@ const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym) } return NULL; } - -void ScriptCState::appendDecls(String8 *str) -{ - ScriptCState::SymbolTable_t *syms = gSyms; - while (syms->mPtr) { - str->append(syms->mRet); - str->append(" "); - str->append(syms->mName); - str->append(syms->mParam); - str->append(";\n"); - syms++; - } -} - - diff --git a/libs/rs/rsScriptC_LibCL.cpp b/libs/rs/rsScriptC_LibCL.cpp new file mode 100644 index 0000000..57855db --- /dev/null +++ b/libs/rs/rsScriptC_LibCL.cpp @@ -0,0 +1,264 @@ +/* + * 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" + +// Implements rs_cl.rsh + + +using namespace android; +using namespace android::renderscript; + + +static float SC_exp10(float v) { + return pow(10.f, v); +} + +static float SC_fract(float v, int *iptr) { + int i = (int)floor(v); + iptr[0] = i; + return fmin(v - i, 0x1.fffffep-1f); +} + +static float SC_log2(float v) { + return log10(v) / log10(2.f); +} + +static float SC_mad(float v1, float v2, float v3) { + return v1 * v2 + v3; +} + +static float SC_pown(float v, int p) { + return powf(v, (float)p); +} + +static float SC_powr(float v, float p) { + return powf(v, p); +} + +float SC_rootn(float v, int r) { + return pow(v, 1.f / r); +} + +float SC_rsqrt(float v) { + return 1.f / sqrtf(v); +} + +float SC_sincos(float v, float *cosptr) { + *cosptr = cosf(v); + return sinf(v); +} + +////////////////////////////////////////////////////////////////////////////// +// Integer +////////////////////////////////////////////////////////////////////////////// + + +static uint32_t SC_abs_i32(int32_t v) {return abs(v);} +static uint16_t SC_abs_i16(int16_t v) {return (uint16_t)abs(v);} +static uint8_t SC_abs_i8(int8_t v) {return (uint8_t)abs(v);} + +static uint32_t SC_clz_u32(uint32_t v) {return __builtin_clz(v);} +static uint16_t SC_clz_u16(uint16_t v) {return (uint16_t)__builtin_clz(v);} +static uint8_t SC_clz_u8(uint8_t v) {return (uint8_t)__builtin_clz(v);} +static int32_t SC_clz_i32(int32_t v) {return (int32_t)__builtin_clz((uint32_t)v);} +static int16_t SC_clz_i16(int16_t v) {return (int16_t)__builtin_clz(v);} +static int8_t SC_clz_i8(int8_t v) {return (int8_t)__builtin_clz(v);} + +static uint32_t SC_max_u32(uint32_t v, uint32_t v2) {return rsMax(v, v2);} +static uint16_t SC_max_u16(uint16_t v, uint16_t v2) {return rsMax(v, v2);} +static uint8_t SC_max_u8(uint8_t v, uint8_t v2) {return rsMax(v, v2);} +static int32_t SC_max_i32(int32_t v, int32_t v2) {return rsMax(v, v2);} +static int16_t SC_max_i16(int16_t v, int16_t v2) {return rsMax(v, v2);} +static int8_t SC_max_i8(int8_t v, int8_t v2) {return rsMax(v, v2);} + +static uint32_t SC_min_u32(uint32_t v, uint32_t v2) {return rsMin(v, v2);} +static uint16_t SC_min_u16(uint16_t v, uint16_t v2) {return rsMin(v, v2);} +static uint8_t SC_min_u8(uint8_t v, uint8_t v2) {return rsMin(v, v2);} +static int32_t SC_min_i32(int32_t v, int32_t v2) {return rsMin(v, v2);} +static int16_t SC_min_i16(int16_t v, int16_t v2) {return rsMin(v, v2);} +static int8_t SC_min_i8(int8_t v, int8_t v2) {return rsMin(v, v2);} + +////////////////////////////////////////////////////////////////////////////// +// Float util +////////////////////////////////////////////////////////////////////////////// + +static float SC_clamp_f32(float amount, float low, float high) { + return amount < low ? low : (amount > high ? high : amount); +} + +static float SC_degrees(float radians) { + return radians * (180.f / M_PI); +} + +static float SC_max_f32(float v, float v2) { + return rsMax(v, v2); +} + +static float SC_min_f32(float v, float v2) { + return rsMin(v, v2); +} + +static float SC_mix_f32(float start, float stop, float amount) { + //LOGE("lerpf %f %f %f", start, stop, amount); + return start + (stop - start) * amount; +} + +static float SC_radians(float degrees) { + return degrees * (M_PI / 180.f); +} + +static float SC_step_f32(float edge, float v) { + if (v < edge) return 0.f; + return 1.f; +} + +static float SC_sign_f32(float value) { + if (value > 0) return 1.f; + if (value < 0) return -1.f; + return value; +} + +////////////////////////////////////////////////////////////////////////////// +// 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[] = { + // OpenCL math + { "_Z4acosf", (void *)&acosf, true }, + { "_Z5acoshf", (void *)&acoshf, true }, + { "_Z4asinf", (void *)&asinf, true }, + { "_Z5asinhf", (void *)&asinhf, true }, + { "_Z4atanf", (void *)&atanf, true }, + { "_Z5atan2ff", (void *)&atan2f, true }, + { "_Z5atanhf", (void *)&atanhf, true }, + { "_Z4cbrtf", (void *)&cbrtf, true }, + { "_Z4ceilf", (void *)&ceilf, true }, + { "_Z8copysignff", (void *)©signf, true }, + { "_Z3cosf", (void *)&cosf, true }, + { "_Z4coshf", (void *)&coshf, true }, + { "_Z4erfcf", (void *)&erfcf, true }, + { "_Z3erff", (void *)&erff, true }, + { "_Z3expf", (void *)&expf, true }, + { "_Z4exp2f", (void *)&exp2f, true }, + { "_Z5exp10f", (void *)&SC_exp10, true }, + { "_Z5expm1f", (void *)&expm1f, true }, + { "_Z4fabsf", (void *)&fabsf, true }, + { "_Z4fdimff", (void *)&fdimf, true }, + { "_Z5floorf", (void *)&floorf, true }, + { "_Z3fmafff", (void *)&fmaf, true }, + { "_Z4fmaxff", (void *)&fmaxf, true }, + { "_Z4fminff", (void *)&fminf, true }, // float fmin(float, float) + { "_Z4fmodff", (void *)&fmodf, true }, + { "_Z5fractfPf", (void *)&SC_fract, true }, + { "_Z5frexpfPi", (void *)&frexpf, true }, + { "_Z5hypotff", (void *)&hypotf, true }, + { "_Z5ilogbf", (void *)&ilogbf, true }, + { "_Z5ldexpfi", (void *)&ldexpf, true }, + { "_Z6lgammaf", (void *)&lgammaf, true }, + { "_Z6lgammafPi", (void *)&lgammaf_r, true }, + { "_Z3logf", (void *)&logf, true }, + { "_Z4log2f", (void *)&SC_log2, true }, + { "_Z5log10f", (void *)&log10f, true }, + { "_Z5log1pf", (void *)&log1pf, true }, + { "_Z4logbf", (void *)&logbf, true }, + { "_Z3madfff", (void *)&SC_mad, true }, + { "_Z4modffPf", (void *)&modff, true }, + //{ "_Z3nanj", (void *)&SC_nan, true }, + { "_Z9nextafterff", (void *)&nextafterf, true }, + { "_Z3powff", (void *)&powf, true }, + { "_Z9remainderff", (void *)&remainderf, true }, + { "_Z6remquoffPi", (void *)&remquof, true }, + { "_Z4rintf", (void *)&rintf, true }, + { "_Z5rootnfi", (void *)&SC_rootn, true }, + { "_Z5roundf", (void *)&roundf, true }, + { "_Z5rsqrtf", (void *)&SC_rsqrt, true }, + { "_Z3sinf", (void *)&sinf, true }, + { "_Z6sincosfPf", (void *)&SC_sincos, true }, + { "_Z4sinhf", (void *)&sinhf, true }, + { "_Z4sqrtf", (void *)&sqrtf, true }, + { "_Z3tanf", (void *)&tanf, true }, + { "_Z4tanhf", (void *)&tanhf, true }, + { "_Z6tgammaf", (void *)&tgammaf, true }, + { "_Z5truncf", (void *)&truncf, true }, + + // OpenCL Int + { "_Z3absi", (void *)&SC_abs_i32, true }, + { "_Z3abss", (void *)&SC_abs_i16, true }, + { "_Z3absc", (void *)&SC_abs_i8, true }, + { "_Z3clzj", (void *)&SC_clz_u32, true }, + { "_Z3clzt", (void *)&SC_clz_u16, true }, + { "_Z3clzh", (void *)&SC_clz_u8, true }, + { "_Z3clzi", (void *)&SC_clz_i32, true }, + { "_Z3clzs", (void *)&SC_clz_i16, true }, + { "_Z3clzc", (void *)&SC_clz_i8, true }, + { "_Z3maxjj", (void *)&SC_max_u32, true }, + { "_Z3maxtt", (void *)&SC_max_u16, true }, + { "_Z3maxhh", (void *)&SC_max_u8, true }, + { "_Z3maxii", (void *)&SC_max_i32, true }, + { "_Z3maxss", (void *)&SC_max_i16, true }, + { "_Z3maxcc", (void *)&SC_max_i8, true }, + { "_Z3minjj", (void *)&SC_min_u32, true }, + { "_Z3mintt", (void *)&SC_min_u16, true }, + { "_Z3minhh", (void *)&SC_min_u8, true }, + { "_Z3minii", (void *)&SC_min_i32, true }, + { "_Z3minss", (void *)&SC_min_i16, true }, + { "_Z3mincc", (void *)&SC_min_i8, true }, + + // OpenCL 6.11.4 + { "_Z5clampfff", (void *)&SC_clamp_f32, true }, + { "_Z7degreesf", (void *)&SC_degrees, true }, + { "_Z3maxff", (void *)&SC_max_f32, true }, + { "_Z3minff", (void *)&SC_min_f32, true }, + { "_Z3mixfff", (void *)&SC_mix_f32, true }, + { "_Z7radiansf", (void *)&SC_radians, true }, + { "_Z4stepff", (void *)&SC_step_f32, true }, + //{ "smoothstep", (void *)&, true }, + { "_Z4signf", (void *)&SC_sign_f32, true }, + + { NULL, NULL, false } +}; + +const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbolCL(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 new file mode 100644 index 0000000..48a0969 --- /dev/null +++ b/libs/rs/rsScriptC_LibGL.cpp @@ -0,0 +1,462 @@ +/* + * 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 "rsMatrix.h" + +#include "utils/Timers.h" + +#define GL_GLEXT_PROTOTYPES + +#include <GLES/gl.h> +#include <GLES/glext.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <time.h> + +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 + + +////////////////////////////////////////////////////////////////////////////// +// 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)); +} + +static void SC_bindSampler(RsProgramFragment vpf, uint32_t slot, RsSampler vs) { + CHECK_OBJ_OR_NULL(vs); + CHECK_OBJ(vpf); + GET_TLS(); + rsi_ProgramBindSampler(rsc, + static_cast<ProgramFragment *>(vpf), + slot, + static_cast<Sampler *>(vs)); +} + +static void SC_bindProgramStore(RsProgramStore pfs) { + CHECK_OBJ_OR_NULL(pfs); + GET_TLS(); + rsi_ContextBindProgramStore(rsc, pfs); +} + +static void SC_bindProgramFragment(RsProgramFragment pf) { + CHECK_OBJ_OR_NULL(pf); + GET_TLS(); + rsi_ContextBindProgramFragment(rsc, pf); +} + +static void SC_bindProgramVertex(RsProgramVertex pv) { + CHECK_OBJ_OR_NULL(pv); + GET_TLS(); + rsi_ContextBindProgramVertex(rsc, pv); +} + +static void SC_bindProgramRaster(RsProgramRaster pv) { + CHECK_OBJ_OR_NULL(pv); + GET_TLS(); + rsi_ContextBindProgramRaster(rsc, pv); +} + +////////////////////////////////////////////////////////////////////////////// +// VP +////////////////////////////////////////////////////////////////////////////// + +static void SC_vpLoadProjectionMatrix(const rsc_Matrix *m) { + GET_TLS(); + rsc->getProgramVertex()->setProjectionMatrix(rsc, m); +} + +static void SC_vpLoadModelMatrix(const rsc_Matrix *m) { + GET_TLS(); + rsc->getProgramVertex()->setModelviewMatrix(rsc, m); +} + +static void SC_vpLoadTextureMatrix(const rsc_Matrix *m) { + GET_TLS(); + 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); + pf->setConstantColor(rsc, r, g, b, a); +} + +static void SC_vpGetProjectionMatrix(rsc_Matrix *m) { + GET_TLS(); + rsc->getProgramVertex()->getProjectionMatrix(rsc, 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(); + if (!rsc->setupCheck()) { + return; + } + + //LOGE("Quad"); + //LOGE("%4.2f, %4.2f, %4.2f", x1, y1, z1); + //LOGE("%4.2f, %4.2f, %4.2f", x2, y2, z2); + //LOGE("%4.2f, %4.2f, %4.2f", x3, y3, z3); + //LOGE("%4.2f, %4.2f, %4.2f", x4, y4, z4); + + 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]; + 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); + + 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); +} + +static void SC_drawSpriteScreenspace(float x, float y, float z, float w, float h) { + GET_TLS(); + ObjectBaseRef<const ProgramVertex> tmp(rsc->getProgramVertex()); + rsc->setProgramVertex(rsc->getDefaultProgramVertex()); + //rsc->setupCheck(); + + //GLint crop[4] = {0, h, w, -h}; + + float sh = rsc->getHeight(); + + SC_drawQuad(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) { + //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); +} + +static void SC_drawMesh(RsMesh vsm) { + CHECK_OBJ(vsm); + GET_TLS(); + Mesh *sm = static_cast<Mesh *>(vsm); + 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); + 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); + 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); + sm->computeBBox(); + *minX = sm->mBBoxMin[0]; + *minY = sm->mBBoxMin[1]; + *minZ = sm->mBBoxMin[2]; + *maxX = sm->mBBoxMax[0]; + *maxY = sm->mBBoxMax[1]; + *maxZ = sm->mBBoxMax[2]; +} + + +////////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////////// + + +static void SC_color(float r, float g, float b, float a) { + GET_TLS(); + ProgramFragment *pf = (ProgramFragment *)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); +} + +static void SC_allocationSyncAll2(RsAllocation va, RsAllocationUsageType source) { + CHECK_OBJ(va); + GET_TLS(); + static_cast<Allocation *>(va)->syncAll(rsc, source); +} + +static void SC_ClearColor(float r, float g, float b, float a) { + GET_TLS(); + rsc->setupProgramStore(); + + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT); +} + +static void SC_ClearDepth(float v) { + GET_TLS(); + rsc->setupProgramStore(); + + glClearDepthf(v); + glClear(GL_DEPTH_BUFFER_BIT); +} + +static uint32_t SC_getWidth() { + GET_TLS(); + return rsc->getWidth(); +} + +static uint32_t SC_getHeight() { + GET_TLS(); + 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(); + rsc->mStateFont.renderText(text, allocSize, x, y); +} + +static void SC_DrawText(const char *text, int x, int y) { + GET_TLS(); + 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) { + if (left) { + *left = metrics->left; + } + if (right) { + *right = metrics->right; + } + if (top) { + *top = metrics->top; + } + if (bottom) { + *bottom = metrics->bottom; + } +} + +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(); + Font::Rect metrics; + rsc->mStateFont.measureText(text, textLen, &metrics); + SC_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(); + size_t textLen = strlen(text); + Font::Rect metrics; + rsc->mStateFont.measureText(text, textLen, &metrics); + SC_setMetrics(&metrics, left, right, top, bottom); +} + +static void SC_BindFont(RsFont font) { + CHECK_OBJ(font); + GET_TLS(); + rsi_ContextBindFont(rsc, font); +} + +static void SC_FontColor(float r, float g, float b, float a) { + GET_TLS(); + 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/rsShaderCache.cpp b/libs/rs/rsShaderCache.cpp index 4711d1b..b958021 100644 --- a/libs/rs/rsShaderCache.cpp +++ b/libs/rs/rsShaderCache.cpp @@ -14,96 +14,120 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" - #include <GLES/gl.h> #include <GLES2/gl2.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#endif //ANDROID_RS_BUILD_FOR_HOST using namespace android; using namespace android::renderscript; -ShaderCache::ShaderCache() -{ - mEntryCount = 0; - mEntryAllocationCount = 16; - mEntries = (entry_t *)calloc(mEntryAllocationCount, sizeof(entry_t)); +ShaderCache::ShaderCache() { + mEntries.setCapacity(16); +} + +ShaderCache::~ShaderCache() { + cleanupAll(); +} + +void ShaderCache::updateUniformArrayData(Context *rsc, Program *prog, uint32_t linkedID, + UniformData *data, const char* logTag, + UniformQueryData **uniformList, uint32_t uniListSize) { + + for (uint32_t ct=0; ct < prog->getUniformCount(); ct++) { + if (data[ct].slot >= 0 && data[ct].arraySize > 1) { + //Iterate over the list of active GL uniforms and find highest array index + for (uint32_t ui = 0; ui < uniListSize; ui ++) { + if (prog->getUniformName(ct) == uniformList[ui]->name) { + data[ct].arraySize = (uint32_t)uniformList[ui]->arraySize; + break; + } + } + } + + if (rsc->props.mLogShaders) { + LOGV("%s U, %s = %d, arraySize = %d\n", logTag, + prog->getUniformName(ct).string(), data[ct].slot, data[ct].arraySize); + } + } } -ShaderCache::~ShaderCache() -{ - for (uint32_t ct=0; ct < mEntryCount; ct++) { - glDeleteProgram(mEntries[ct].program); +void ShaderCache::populateUniformData(Program *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); } +} - mEntryCount = 0; - mEntryAllocationCount = 0; - free(mEntries); +bool ShaderCache::hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag) { + UniformData *data = mCurrent->vtxUniforms; + for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) { + if (data[ct].slot >= 0 && data[ct].arraySize > 1) { + return true; + } + } + data = mCurrent->fragUniforms; + for (uint32_t ct=0; ct < frag->getUniformCount(); ct++) { + if (data[ct].slot >= 0 && data[ct].arraySize > 1) { + return true; + } + } + return false; } -bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag) -{ +bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag) { if (!vtx->getShaderID()) { vtx->loadShader(rsc); } if (!frag->getShaderID()) { frag->loadShader(rsc); } - //LOGV("ShaderCache lookup vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID()); - for (uint32_t ct=0; ct < mEntryCount; ct++) { - if ((mEntries[ct].vtx == vtx->getShaderID()) && - (mEntries[ct].frag == frag->getShaderID())) { + // Don't try to cache if shaders failed to load + if (!vtx->getShaderID() || !frag->getShaderID()) { + return false; + } + //LOGV("ShaderCache lookup vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID()); + uint32_t entryCount = mEntries.size(); + for (uint32_t ct = 0; ct < entryCount; ct ++) { + if ((mEntries[ct]->vtx == vtx->getShaderID()) && + (mEntries[ct]->frag == frag->getShaderID())) { - //LOGV("SC using program %i", mEntries[ct].program); - glUseProgram(mEntries[ct].program); - mCurrent = &mEntries[ct]; + //LOGV("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)"); return true; } } - // Not in cache, add it. - - if (mEntryAllocationCount == mEntryCount) { - // Out of space, make some. - mEntryAllocationCount *= 2; - entry_t *e = (entry_t *)calloc(mEntryAllocationCount, sizeof(entry_t)); - if (!e) { - LOGE("Out of memory for ShaderCache::lookup"); - return false; - } - memcpy(e, mEntries, sizeof(entry_t) * mEntryCount); - free(mEntries); - mEntries = e; - } - //LOGV("ShaderCache miss, using %i", mEntryCount); + //LOGV("ShaderCache miss"); //LOGE("e0 %x", glGetError()); - - entry_t *e = &mEntries[mEntryCount]; + ProgramEntry *e = new ProgramEntry(vtx->getAttribCount(), + vtx->getUniformCount(), + frag->getUniformCount()); + mEntries.push(e); mCurrent = e; e->vtx = vtx->getShaderID(); e->frag = frag->getShaderID(); e->program = glCreateProgram(); - e->mUserVertexProgram = vtx->isUserProgram(); - if (mEntries[mEntryCount].program) { + if (e->program) { GLuint pgm = e->program; glAttachShader(pgm, vtx->getShaderID()); //LOGE("e1 %x", glGetError()); glAttachShader(pgm, frag->getShaderID()); if (!vtx->isUserProgram()) { - glBindAttribLocation(pgm, 0, "ATTRIB_LegacyPosition"); - glBindAttribLocation(pgm, 1, "ATTRIB_LegacyColor"); - glBindAttribLocation(pgm, 2, "ATTRIB_LegacyNormal"); - glBindAttribLocation(pgm, 3, "ATTRIB_LegacyPointSize"); - glBindAttribLocation(pgm, 4, "ATTRIB_LegacyTexture"); - e->mVtxAttribSlots[RS_KIND_POSITION] = 0; - e->mVtxAttribSlots[RS_KIND_COLOR] = 1; - e->mVtxAttribSlots[RS_KIND_NORMAL] = 2; - e->mVtxAttribSlots[RS_KIND_POINT_SIZE] = 3; - e->mVtxAttribSlots[RS_KIND_TEXTURE] = 4; + glBindAttribLocation(pgm, 0, "ATTRIB_position"); + glBindAttribLocation(pgm, 1, "ATTRIB_color"); + glBindAttribLocation(pgm, 2, "ATTRIB_normal"); + glBindAttribLocation(pgm, 3, "ATTRIB_texture0"); } //LOGE("e2 %x", glGetError()); @@ -123,48 +147,111 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag } } glDeleteProgram(pgm); - rsc->setError(RS_ERROR_BAD_SHADER, "Error linking GL Programs"); + rsc->setError(RS_ERROR_FATAL_PROGRAM_LINK, "Error linking GL Programs"); return false; } - if (vtx->isUserProgram()) { - for (uint32_t ct=0; ct < vtx->getAttribCount(); ct++) { - e->mVtxAttribSlots[ct] = glGetAttribLocation(pgm, vtx->getAttribName(ct)); - if (rsc->props.mLogShaders) { - LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->mVtxAttribSlots[ct]); - } + + for (uint32_t ct=0; ct < e->vtxAttrCount; ct++) { + e->vtxAttrs[ct].slot = glGetAttribLocation(pgm, vtx->getAttribName(ct)); + e->vtxAttrs[ct].name = vtx->getAttribName(ct).string(); + if (rsc->props.mLogShaders) { + LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->vtxAttrs[ct].slot); } } - for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) { - e->mVtxUniformSlots[ct] = glGetUniformLocation(pgm, vtx->getUniformName(ct)); - if (rsc->props.mLogShaders) { - LOGV("vtx U, %s = %d\n", vtx->getUniformName(ct).string(), e->mVtxUniformSlots[ct]); + + populateUniformData(vtx, pgm, e->vtxUniforms); + populateUniformData(frag, pgm, e->fragUniforms); + + // Only populate this list if we have arrays in our uniforms + UniformQueryData **uniformList = NULL; + GLint numUniforms = 0; + bool hasArrays = hasArrayUniforms(vtx, frag); + if (hasArrays) { + // Get the number of active uniforms and the length of the longest name + glGetProgramiv(pgm, GL_ACTIVE_UNIFORMS, &numUniforms); + GLint maxNameLength = 0; + glGetProgramiv(pgm, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); + if (numUniforms > 0 && maxNameLength > 0) { + uniformList = new UniformQueryData*[numUniforms]; + // Iterate over all the uniforms and build the list we + // can later use to match our uniforms to + for (uint32_t ct = 0; ct < (uint32_t)numUniforms; ct++) { + uniformList[ct] = new UniformQueryData(maxNameLength); + glGetActiveUniform(pgm, ct, maxNameLength, &uniformList[ct]->writtenLength, + &uniformList[ct]->arraySize, &uniformList[ct]->type, + uniformList[ct]->name); + //LOGE("GL UNI idx=%u, arraySize=%u, name=%s", ct, + // uniformList[ct]->arraySize, uniformList[ct]->name); + } } } - for (uint32_t ct=0; ct < frag->getUniformCount(); ct++) { - e->mFragUniformSlots[ct] = glGetUniformLocation(pgm, frag->getUniformName(ct)); - if (rsc->props.mLogShaders) { - LOGV("frag U, %s = %d\n", frag->getUniformName(ct).string(), e->mFragUniformSlots[ct]); + + // We now know the highest index of all of the array uniforms + // and we need to update our cache to reflect that + // we may have declared [n], but only m < n elements are used + updateUniformArrayData(rsc, vtx, pgm, e->vtxUniforms, "vtx", + uniformList, (uint32_t)numUniforms); + updateUniformArrayData(rsc, frag, pgm, e->fragUniforms, "frag", + uniformList, (uint32_t)numUniforms); + + // Clean up the uniform data from GL + if (uniformList != NULL) { + for (uint32_t ct = 0; ct < (uint32_t)numUniforms; ct++) { + delete uniformList[ct]; } + delete[] uniformList; + uniformList = NULL; } } - e->mIsValid = true; //LOGV("SC made program %i", e->program); glUseProgram(e->program); - mEntryCount++; rsc->checkError("ShaderCache::lookup (miss)"); return true; } -void ShaderCache::cleanupVertex(uint32_t id) -{ +int32_t ShaderCache::vtxAttribSlot(const String8 &attrName) const { + for (uint32_t ct=0; ct < mCurrent->vtxAttrCount; ct++) { + if (attrName == mCurrent->vtxAttrs[ct].name) { + return mCurrent->vtxAttrs[ct].slot; + } + } + return -1; } -void ShaderCache::cleanupFragment(uint32_t id) -{ +void ShaderCache::cleanupVertex(uint32_t id) { + int32_t numEntries = (int32_t)mEntries.size(); + for (int32_t ct = 0; ct < numEntries; ct ++) { + if (mEntries[ct]->vtx == id) { + glDeleteProgram(mEntries[ct]->program); + + delete mEntries[ct]; + mEntries.removeAt(ct); + numEntries = (int32_t)mEntries.size(); + ct --; + } + } } -void ShaderCache::cleanupAll() -{ +void ShaderCache::cleanupFragment(uint32_t id) { + int32_t numEntries = (int32_t)mEntries.size(); + for (int32_t ct = 0; ct < numEntries; ct ++) { + if (mEntries[ct]->frag == id) { + glDeleteProgram(mEntries[ct]->program); + + delete mEntries[ct]; + mEntries.removeAt(ct); + numEntries = (int32_t)mEntries.size(); + ct --; + } + } +} + +void ShaderCache::cleanupAll() { + for (uint32_t ct=0; ct < mEntries.size(); ct++) { + glDeleteProgram(mEntries[ct]->program); + free(mEntries[ct]); + } + mEntries.clear(); } diff --git a/libs/rs/rsShaderCache.h b/libs/rs/rsShaderCache.h index df99ccc..3540366 100644 --- a/libs/rs/rsShaderCache.h +++ b/libs/rs/rsShaderCache.h @@ -27,8 +27,7 @@ namespace renderscript { // An element is a group of Components that occupies one cell in a structure. -class ShaderCache -{ +class ShaderCache { public: ShaderCache(); virtual ~ShaderCache(); @@ -40,30 +39,86 @@ public: void cleanupAll(); - int32_t vtxAttribSlot(uint32_t a) const {return mCurrent->mVtxAttribSlots[a];} - int32_t vtxUniformSlot(uint32_t a) const {return mCurrent->mVtxUniformSlots[a];} - int32_t fragAttribSlot(uint32_t a) const {return mCurrent->mFragAttribSlots[a];} - int32_t fragUniformSlot(uint32_t a) const {return mCurrent->mFragUniformSlots[a];} - bool isUserVertexProgram() const {return mCurrent->mUserVertexProgram;} + int32_t vtxAttribSlot(const 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: - typedef struct { + struct UniformQueryData { + char *name; + uint32_t nameLength; + int32_t writtenLength; + int32_t arraySize; + uint32_t type; + UniformQueryData(uint32_t maxName) { + name = NULL; + nameLength = maxName; + if (nameLength > 0 ) { + name = new char[nameLength]; + } + } + ~UniformQueryData() { + if (name != NULL) { + delete[] name; + name = NULL; + } + } + }; + struct UniformData { + int32_t slot; + uint32_t arraySize; + }; + struct AttrData { + int32_t slot; + const char* name; + }; + struct ProgramEntry { + ProgramEntry(uint32_t numVtxAttr, uint32_t numVtxUnis, + uint32_t numFragUnis) : vtx(0), frag(0), program(0), vtxAttrCount(0), + vtxAttrs(0), vtxUniforms(0), fragUniforms(0) { + vtxAttrCount = numVtxAttr; + if (numVtxAttr) { + vtxAttrs = new AttrData[numVtxAttr]; + } + if (numVtxUnis) { + vtxUniforms = new UniformData[numVtxUnis]; + } + if (numFragUnis) { + fragUniforms = new UniformData[numFragUnis]; + } + } + ~ProgramEntry() { + if (vtxAttrs) { + delete[] vtxAttrs; + vtxAttrs = NULL; + } + if (vtxUniforms) { + delete[] vtxUniforms; + vtxUniforms = NULL; + } + if (fragUniforms) { + delete[] fragUniforms; + fragUniforms = NULL; + } + } uint32_t vtx; uint32_t frag; uint32_t program; - int32_t mVtxAttribSlots[Program::MAX_ATTRIBS]; - int32_t mVtxUniformSlots[Program::MAX_UNIFORMS]; - int32_t mFragAttribSlots[Program::MAX_ATTRIBS]; - int32_t mFragUniformSlots[Program::MAX_UNIFORMS]; - bool mUserVertexProgram; - bool mIsValid; - } entry_t; - entry_t *mEntries; - entry_t *mCurrent; - - uint32_t mEntryCount; - uint32_t mEntryAllocationCount; - + uint32_t vtxAttrCount; + AttrData *vtxAttrs; + UniformData *vtxUniforms; + UniformData *fragUniforms; + }; + 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, + UniformData *data, const char* logTag, + UniformQueryData **uniformList, uint32_t uniListSize); }; diff --git a/libs/rs/rsSignal.cpp b/libs/rs/rsSignal.cpp new file mode 100644 index 0000000..ccd20b9 --- /dev/null +++ b/libs/rs/rsSignal.cpp @@ -0,0 +1,93 @@ +/* + * 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 "rsSignal.h" + +using namespace android; +using namespace android::renderscript; + + +Signal::Signal() { + mSet = true; +} + +Signal::~Signal() { + pthread_mutex_destroy(&mMutex); + pthread_cond_destroy(&mCondition); +} + +bool Signal::init() { + int status = pthread_mutex_init(&mMutex, NULL); + if (status) { + LOGE("LocklessFifo mutex init failure"); + return false; + } + + status = pthread_cond_init(&mCondition, NULL); + if (status) { + LOGE("LocklessFifo condition init failure"); + pthread_mutex_destroy(&mMutex); + return false; + } + + return true; +} + +void Signal::set() { + int status; + + status = pthread_mutex_lock(&mMutex); + if (status) { + LOGE("LocklessCommandFifo: error %i locking for set condition.", status); + return; + } + + mSet = true; + + status = pthread_cond_signal(&mCondition); + if (status) { + LOGE("LocklessCommandFifo: error %i on set condition.", status); + } + + status = pthread_mutex_unlock(&mMutex); + if (status) { + LOGE("LocklessCommandFifo: error %i unlocking for set condition.", status); + } +} + +void Signal::wait() { + int status; + + status = pthread_mutex_lock(&mMutex); + if (status) { + LOGE("LocklessCommandFifo: error %i locking for condition.", status); + return; + } + + if (!mSet) { + status = pthread_cond_wait(&mCondition, &mMutex); + if (status) { + LOGE("LocklessCommandFifo: error %i waiting on condition.", status); + } + } + mSet = false; + + status = pthread_mutex_unlock(&mMutex); + if (status) { + LOGE("LocklessCommandFifo: error %i unlocking for condition.", status); + } +} + diff --git a/libs/rs/rsFileA3DDecls.h b/libs/rs/rsSignal.h index 2a08bd3..2e760f1 100644 --- a/libs/rs/rsFileA3DDecls.h +++ b/libs/rs/rsSignal.h @@ -14,31 +14,33 @@ * limitations under the License. */ -#ifndef ANDROID_RS_FILE_A3D_DECLS_H -#define ANDROID_RS_FILE_A3D_DECLS_H +#ifndef ANDROID_RS_SIGNAL_H +#define ANDROID_RS_SIGNAL_H -#define A3D_MAGIC_KEY "Android3D_ff" +#include "rsUtils.h" namespace android { namespace renderscript { - enum A3DChunkType { - CHUNK_EMPTY, +class Signal { +public: + Signal(); + ~Signal(); - CHUNK_ELEMENT, - CHUNK_ELEMENT_SOURCE, - CHUNK_VERTICIES, - CHUNK_MESH, - CHUNK_PRIMITIVE, + bool init(); - CHUNK_LAST - }; + void set(); + void wait(); +protected: + bool mSet; + pthread_mutex_t mMutex; + pthread_cond_t mCondition; +}; } } -#endif //ANDROID_RS_FILE_A3D_H - +#endif diff --git a/libs/rs/rsSimpleMesh.cpp b/libs/rs/rsSimpleMesh.cpp deleted file mode 100644 index 53ce5cd..0000000 --- a/libs/rs/rsSimpleMesh.cpp +++ /dev/null @@ -1,169 +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 "rsContext.h" - -using namespace android; -using namespace android::renderscript; - -#include <GLES/gl.h> -#include <GLES/glext.h> - -SimpleMesh::SimpleMesh(Context *rsc) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; -} - -SimpleMesh::~SimpleMesh() -{ - delete[] mVertexTypes; - delete[] mVertexBuffers; -} - -void SimpleMesh::render(Context *rsc) const -{ - if (mPrimitiveType.get()) { - renderRange(rsc, 0, mPrimitiveType->getDimX()); - return; - } - - if (mIndexType.get()) { - renderRange(rsc, 0, mIndexType->getDimX()); - return; - } - - renderRange(rsc, 0, mVertexTypes[0]->getDimX()); -} - -void SimpleMesh::renderRange(Context *rsc, uint32_t start, uint32_t len) const -{ - if (len < 1) { - return; - } - - rsc->checkError("SimpleMesh::renderRange 1"); - VertexArray va; - if (rsc->checkVersion2_0()) { - for (uint32_t ct=0; ct < mVertexTypeCount; ct++) { - mVertexBuffers[ct]->uploadCheck(rsc); - va.setActiveBuffer(mVertexBuffers[ct]->getBufferObjectID()); - mVertexTypes[ct]->enableGLVertexBuffer2(&va); - } - va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache); - } else { - for (uint32_t ct=0; ct < mVertexTypeCount; ct++) { - mVertexBuffers[ct]->uploadCheck(rsc); - va.setActiveBuffer(mVertexBuffers[ct]->getBufferObjectID()); - mVertexTypes[ct]->enableGLVertexBuffer(&va); - } - va.setupGL(rsc, 0); - } - - rsc->checkError("SimpleMesh::renderRange 2"); - if (mIndexType.get()) { - mIndexBuffer->uploadCheck(rsc); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); - glDrawElements(mGLPrimitive, len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2)); - } else { - glDrawArrays(mGLPrimitive, start, len); - } - - rsc->checkError("SimpleMesh::renderRange"); -} - -void SimpleMesh::uploadAll(Context *rsc) -{ - for (uint32_t ct=0; ct < mVertexTypeCount; ct++) { - if (mVertexBuffers[ct].get()) { - mVertexBuffers[ct]->deferedUploadToBufferObject(rsc); - } - } - if (mIndexBuffer.get()) { - mIndexBuffer->deferedUploadToBufferObject(rsc); - } - if (mPrimitiveBuffer.get()) { - mPrimitiveBuffer->deferedUploadToBufferObject(rsc); - } - rsc->checkError("SimpleMesh::uploadAll"); -} - - -SimpleMeshContext::SimpleMeshContext() -{ -} - -SimpleMeshContext::~SimpleMeshContext() -{ -} - - -namespace android { -namespace renderscript { - - -RsSimpleMesh rsi_SimpleMeshCreate(Context *rsc, RsType prim, RsType idx, RsType *vtx, uint32_t vtxCount, uint32_t primType) -{ - SimpleMesh *sm = new SimpleMesh(rsc); - sm->incUserRef(); - - sm->mIndexType.set((const Type *)idx); - sm->mPrimitiveType.set((const Type *)prim); - - sm->mVertexTypeCount = vtxCount; - sm->mVertexTypes = new ObjectBaseRef<const Type>[vtxCount]; - sm->mVertexBuffers = new ObjectBaseRef<Allocation>[vtxCount]; - for (uint32_t ct=0; ct < vtxCount; ct++) { - sm->mVertexTypes[ct].set((const Type *)vtx[ct]); - } - - sm->mPrimitive = (RsPrimitive)primType; - switch(sm->mPrimitive) { - case RS_PRIMITIVE_POINT: sm->mGLPrimitive = GL_POINTS; break; - case RS_PRIMITIVE_LINE: sm->mGLPrimitive = GL_LINES; break; - case RS_PRIMITIVE_LINE_STRIP: sm->mGLPrimitive = GL_LINE_STRIP; break; - case RS_PRIMITIVE_TRIANGLE: sm->mGLPrimitive = GL_TRIANGLES; break; - case RS_PRIMITIVE_TRIANGLE_STRIP: sm->mGLPrimitive = GL_TRIANGLE_STRIP; break; - case RS_PRIMITIVE_TRIANGLE_FAN: sm->mGLPrimitive = GL_TRIANGLE_FAN; break; - } - return sm; -} - -void rsi_SimpleMeshBindVertex(Context *rsc, RsSimpleMesh mv, RsAllocation va, uint32_t slot) -{ - SimpleMesh *sm = static_cast<SimpleMesh *>(mv); - rsAssert(slot < sm->mVertexTypeCount); - - sm->mVertexBuffers[slot].set((Allocation *)va); -} - -void rsi_SimpleMeshBindIndex(Context *rsc, RsSimpleMesh mv, RsAllocation va) -{ - SimpleMesh *sm = static_cast<SimpleMesh *>(mv); - sm->mIndexBuffer.set((Allocation *)va); -} - -void rsi_SimpleMeshBindPrimitive(Context *rsc, RsSimpleMesh mv, RsAllocation va) -{ - SimpleMesh *sm = static_cast<SimpleMesh *>(mv); - sm->mPrimitiveBuffer.set((Allocation *)va); -} - - - - -}} - diff --git a/libs/rs/rsSimpleMesh.h b/libs/rs/rsSimpleMesh.h deleted file mode 100644 index 6defbda..0000000 --- a/libs/rs/rsSimpleMesh.h +++ /dev/null @@ -1,69 +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. - */ - -#ifndef ANDROID_RS_SIMPLE_MESH_H -#define ANDROID_RS_SIMPLE_MESH_H - - -#include "RenderScript.h" - -// --------------------------------------------------------------------------- -namespace android { -namespace renderscript { - - -// An element is a group of Components that occupies one cell in a structure. -class SimpleMesh : public ObjectBase -{ -public: - SimpleMesh(Context *); - ~SimpleMesh(); - - ObjectBaseRef<const Type> mIndexType; - ObjectBaseRef<const Type> mPrimitiveType; - ObjectBaseRef<const Type> *mVertexTypes; - uint32_t mVertexTypeCount; - - ObjectBaseRef<Allocation> mIndexBuffer; - ObjectBaseRef<Allocation> mPrimitiveBuffer; - ObjectBaseRef<Allocation> *mVertexBuffers; - - RsPrimitive mPrimitive; - uint32_t mGLPrimitive; - - - void render(Context *) const; - void renderRange(Context *, uint32_t start, uint32_t len) const; - void uploadAll(Context *); - - -protected: -}; - -class SimpleMeshContext -{ -public: - SimpleMeshContext(); - ~SimpleMeshContext(); - - -}; - - -} -} -#endif //ANDROID_RS_SIMPLE_MESH_H - diff --git a/libs/rs/rsStream.cpp b/libs/rs/rsStream.cpp new file mode 100644 index 0000000..49ed567 --- /dev/null +++ b/libs/rs/rsStream.cpp @@ -0,0 +1,118 @@ + +/* + * 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. + */ + +#ifndef ANDROID_RS_BUILD_FOR_HOST +#include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif + +#include "rsStream.h" + +using namespace android; +using namespace android::renderscript; + +IStream::IStream(const uint8_t *buf, bool use64) { + mData = buf; + mPos = 0; + mUse64 = use64; +} + +void IStream::loadByteArray(void *dest, size_t numBytes) { + memcpy(dest, mData + mPos, numBytes); + mPos += numBytes; +} + +uint64_t IStream::loadOffset() { + uint64_t tmp; + if (mUse64) { + mPos = (mPos + 7) & (~7); + tmp = reinterpret_cast<const uint64_t *>(&mData[mPos])[0]; + mPos += sizeof(uint64_t); + return tmp; + } + return loadU32(); +} + +void IStream::loadString(String8 *s) { + uint32_t len = loadU32(); + s->setTo((const char *)&mData[mPos], len); + mPos += len; +} + +// Output stream implementation +OStream::OStream(uint64_t len, bool use64) { + mData = (uint8_t*)malloc(len); + mLength = len; + mPos = 0; + mUse64 = use64; +} + +OStream::~OStream() { + free(mData); +} + +void OStream::addByteArray(const void *src, size_t numBytes) { + // We need to potentially grow more than once if the number of byes we write is substantial + while (mPos + numBytes >= mLength) { + growSize(); + } + memcpy(mData + mPos, src, numBytes); + mPos += numBytes; +} + +void OStream::addOffset(uint64_t v) { + if (mUse64) { + mPos = (mPos + 7) & (~7); + if (mPos + sizeof(v) >= mLength) { + growSize(); + } + mData[mPos++] = (uint8_t)(v & 0xff); + mData[mPos++] = (uint8_t)((v >> 8) & 0xff); + mData[mPos++] = (uint8_t)((v >> 16) & 0xff); + mData[mPos++] = (uint8_t)((v >> 24) & 0xff); + mData[mPos++] = (uint8_t)((v >> 32) & 0xff); + mData[mPos++] = (uint8_t)((v >> 40) & 0xff); + mData[mPos++] = (uint8_t)((v >> 48) & 0xff); + mData[mPos++] = (uint8_t)((v >> 56) & 0xff); + } else { + addU32(v); + } +} + +void OStream::addString(String8 *s) { + uint32_t len = s->size(); + addU32(len); + if (mPos + len*sizeof(char) >= mLength) { + growSize(); + } + char *stringData = reinterpret_cast<char *>(&mData[mPos]); + for (uint32_t i = 0; i < len; i ++) { + stringData[i] = s->string()[i]; + } + mPos += len*sizeof(char); +} + +void OStream::growSize() { + uint8_t *newData = (uint8_t*)malloc(mLength*2); + memcpy(newData, mData, mLength*sizeof(uint8_t)); + mLength = mLength * 2; + free(mData); + mData = newData; +} + + diff --git a/libs/rs/rsStream.h b/libs/rs/rsStream.h new file mode 100644 index 0000000..62bcf94 --- /dev/null +++ b/libs/rs/rsStream.h @@ -0,0 +1,161 @@ +/* + * 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. + */ + +#ifndef ANDROID_RS_STREAM_H +#define ANDROID_RS_STREAM_H + +#include <utils/String8.h> +#include <stdio.h> + +// --------------------------------------------------------------------------- +namespace android { +namespace renderscript { + +class IStream { +public: + IStream(const uint8_t *, bool use64); + + float loadF() { + mPos = (mPos + 3) & (~3); + float tmp = reinterpret_cast<const float *>(&mData[mPos])[0]; + mPos += sizeof(float); + return tmp; + } + int32_t loadI32() { + mPos = (mPos + 3) & (~3); + int32_t tmp = reinterpret_cast<const int32_t *>(&mData[mPos])[0]; + mPos += sizeof(int32_t); + return tmp; + } + uint32_t loadU32() { + mPos = (mPos + 3) & (~3); + uint32_t tmp = reinterpret_cast<const uint32_t *>(&mData[mPos])[0]; + mPos += sizeof(uint32_t); + return tmp; + } + uint16_t loadU16() { + mPos = (mPos + 1) & (~1); + uint16_t tmp = reinterpret_cast<const uint16_t *>(&mData[mPos])[0]; + mPos += sizeof(uint16_t); + return tmp; + } + inline uint8_t loadU8() { + uint8_t tmp = reinterpret_cast<const uint8_t *>(&mData[mPos])[0]; + mPos += sizeof(uint8_t); + return tmp; + } + void loadByteArray(void *dest, size_t numBytes); + uint64_t loadOffset(); + void loadString(String8 *s); + uint64_t getPos() const { + return mPos; + } + void reset(uint64_t pos) { + mPos = pos; + } + void reset() { + mPos = 0; + } + + const uint8_t * getPtr() const { + return mData; + } +protected: + const uint8_t * mData; + uint64_t mPos; + bool mUse64; +}; + +class OStream { +public: + OStream(uint64_t length, bool use64); + ~OStream(); + + void align(uint32_t bytes) { + mPos = (mPos + (bytes - 1)) & (~(bytes - 1)); + if (mPos >= mLength) { + growSize(); + } + } + + void addF(float v) { + uint32_t uintV = *reinterpret_cast<uint32_t*> (&v); + addU32(uintV); + } + void addI32(int32_t v) { + mPos = (mPos + 3) & (~3); + if (mPos + sizeof(v) >= mLength) { + growSize(); + } + mData[mPos++] = (uint8_t)(v & 0xff); + mData[mPos++] = (uint8_t)((v >> 8) & 0xff); + mData[mPos++] = (uint8_t)((v >> 16) & 0xff); + mData[mPos++] = (uint8_t)((v >> 24) & 0xff); + } + void addU32(uint32_t v) { + mPos = (mPos + 3) & (~3); + if (mPos + sizeof(v) >= mLength) { + growSize(); + } + mData[mPos++] = (uint8_t)(v & 0xff); + mData[mPos++] = (uint8_t)((v >> 8) & 0xff); + mData[mPos++] = (uint8_t)((v >> 16) & 0xff); + mData[mPos++] = (uint8_t)((v >> 24) & 0xff); + } + void addU16(uint16_t v) { + mPos = (mPos + 1) & (~1); + if (mPos + sizeof(v) >= mLength) { + growSize(); + } + mData[mPos++] = (uint8_t)(v & 0xff); + mData[mPos++] = (uint8_t)(v >> 8); + } + inline void addU8(uint8_t v) { + if (mPos + 1 >= mLength) { + growSize(); + } + reinterpret_cast<uint8_t *>(&mData[mPos])[0] = v; + mPos ++; + } + void addByteArray(const void *src, size_t numBytes); + void addOffset(uint64_t v); + void addString(String8 *s); + uint64_t getPos() const { + return mPos; + } + void reset(uint64_t pos) { + mPos = pos; + } + void reset() { + mPos = 0; + } + const uint8_t * getPtr() const { + return mData; + } +protected: + void growSize(); + uint8_t * mData; + uint64_t mLength; + uint64_t mPos; + bool mUse64; +}; + + +} // renderscript +} // android +#endif //ANDROID_RS_STREAM_H + + diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp index 527b3d7..6cf07de 100644 --- a/libs/rs/rsThreadIO.cpp +++ b/libs/rs/rsThreadIO.cpp @@ -21,25 +21,21 @@ using namespace android; using namespace android::renderscript; -ThreadIO::ThreadIO() -{ +ThreadIO::ThreadIO() { mToCore.init(16 * 1024); mToClient.init(1024); } -ThreadIO::~ThreadIO() -{ +ThreadIO::~ThreadIO() { } -void ThreadIO::shutdown() -{ +void ThreadIO::shutdown() { mToCore.shutdown(); } -bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) -{ +bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) { bool ret = false; - while(!mToCore.isEmpty() || waitForCommand) { + while (!mToCore.isEmpty() || waitForCommand) { uint32_t cmdID = 0; uint32_t cmdSize = 0; ret = true; @@ -57,6 +53,11 @@ bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) waitForCommand = false; //LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize); + if (cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) { + rsAssert(cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *))); + LOGE("playCoreCommands error con %p, cmd %i", con, cmdID); + mToCore.printDebugData(); + } gPlaybackFuncs[cmdID](con, data); mToCore.next(); } diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h index 95270f5..f9d0de7 100644 --- a/libs/rs/rsThreadIO.h +++ b/libs/rs/rsThreadIO.h @@ -42,7 +42,6 @@ public: LocklessCommandFifo mToClient; intptr_t mToCoreRet; - }; diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp index c09e979..d7b5f12 100644 --- a/libs/rs/rsType.cpp +++ b/libs/rs/rsType.cpp @@ -14,36 +14,40 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" #include <GLES/gl.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#endif using namespace android; using namespace android::renderscript; -Type::Type(Context *rsc) : ObjectBase(rsc) -{ - mAllocFile = __FILE__; - mAllocLine = __LINE__; +Type::Type(Context *rsc) : ObjectBase(rsc) { mLODs = 0; mLODCount = 0; clear(); } -Type::~Type() -{ +void Type::preDestroy() { for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) { if (mRSC->mStateType.mTypes[ct] == this) { mRSC->mStateType.mTypes.removeAt(ct); break; } } +} + +Type::~Type() { if (mLODs) { delete [] mLODs; + mLODs = NULL; } } -void Type::clear() -{ +void Type::clear() { if (mLODs) { delete [] mLODs; mLODs = NULL; @@ -56,22 +60,18 @@ void Type::clear() mElement.clear(); } -TypeState::TypeState() -{ +TypeState::TypeState() { } -TypeState::~TypeState() -{ +TypeState::~TypeState() { } -size_t Type::getOffsetForFace(uint32_t face) const -{ +size_t Type::getOffsetForFace(uint32_t face) const { rsAssert(mFaces); return 0; } -void Type::compute() -{ +void Type::compute() { uint32_t oldLODCount = mLODCount; if (mDimLOD) { uint32_t l2x = rsFindHighBit(mDimX) + 1; @@ -84,7 +84,9 @@ void Type::compute() mLODCount = 1; } if (mLODCount != oldLODCount) { - delete [] mLODs; + if (mLODs){ + delete [] mLODs; + } mLODs = new LOD[mLODCount]; } @@ -110,181 +112,87 @@ void Type::compute() offset *= 6; } mTotalSizeBytes = offset; - - makeGLComponents(); } -uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const -{ +uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const { uint32_t offset = mLODs[lod].mOffset; offset += x * mElement->getSizeBytes(); return offset; } -uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const -{ +uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const { uint32_t offset = mLODs[lod].mOffset; offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes(); return offset; } -uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const -{ +uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const { uint32_t offset = mLODs[lod].mOffset; offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes(); return offset; } +uint32_t Type::getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const { + uint32_t offset = mLODs[lod].mOffset; + offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes(); -void Type::makeGLComponents() -{ - uint32_t userNum = 0; - - for (uint32_t ct=0; ct < getElement()->getFieldCount(); ct++) { - const Component &c = getElement()->getField(ct)->getComponent(); - - switch(c.getKind()) { - case RS_KIND_USER: - mGL.mUser[userNum].size = c.getVectorSize(); - mGL.mUser[userNum].offset = mElement->getFieldOffsetBytes(ct); - mGL.mUser[userNum].type = c.getGLType(); - mGL.mUser[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized(); - mGL.mUser[userNum].name.setTo(getElement()->getFieldName(ct)); - userNum ++; - break; - - case RS_KIND_POSITION: - rsAssert(mGL.mVtx.size == 0); - mGL.mVtx.size = c.getVectorSize(); - mGL.mVtx.offset = mElement->getFieldOffsetBytes(ct); - mGL.mVtx.type = c.getGLType(); - mGL.mVtx.normalized = false; - mGL.mVtx.name.setTo("Position"); - break; - - case RS_KIND_COLOR: - rsAssert(mGL.mColor.size == 0); - mGL.mColor.size = c.getVectorSize(); - mGL.mColor.offset = mElement->getFieldOffsetBytes(ct); - mGL.mColor.type = c.getGLType(); - mGL.mColor.normalized = c.getType() != RS_TYPE_FLOAT_32; - mGL.mColor.name.setTo("Color"); - break; - - case RS_KIND_NORMAL: - rsAssert(mGL.mNorm.size == 0); - mGL.mNorm.size = c.getVectorSize(); - mGL.mNorm.offset = mElement->getFieldOffsetBytes(ct); - mGL.mNorm.type = c.getGLType(); - mGL.mNorm.normalized = false; - mGL.mNorm.name.setTo("Normal"); - break; - - case RS_KIND_TEXTURE: - rsAssert(mGL.mTex.size == 0); - mGL.mTex.size = c.getVectorSize(); - mGL.mTex.offset = mElement->getFieldOffsetBytes(ct); - mGL.mTex.type = c.getGLType(); - mGL.mTex.normalized = false; - mGL.mTex.name.setTo("Texture"); - break; - - case RS_KIND_POINT_SIZE: - rsAssert(!mGL.mPointSize.size); - mGL.mPointSize.size = c.getVectorSize(); - mGL.mPointSize.offset = mElement->getFieldOffsetBytes(ct); - mGL.mPointSize.type = c.getGLType(); - mGL.mPointSize.normalized = false; - mGL.mPointSize.name.setTo("PointSize"); - break; - - default: - break; - } + if (face != 0) { + uint32_t faceOffset = getSizeBytes() / 6; + offset += faceOffset * face; } + return offset; } -void Type::enableGLVertexBuffer(VertexArray *va) const -{ - // Note: We are only going to enable buffers and never disable them - // here. The reason is more than one Allocation may be used as a vertex - // source. So we cannot disable arrays that may have been in use by - // another allocation. - - uint32_t stride = mElement->getSizeBytes(); - if (mGL.mVtx.size) { - va->addLegacy(mGL.mVtx.type, - mGL.mVtx.size, - stride, - RS_KIND_POSITION, - false, - mGL.mVtx.offset); - } +void Type::dumpLOGV(const char *prefix) const { + char buf[1024]; + ObjectBase::dumpLOGV(prefix); + LOGV("%s Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces); + snprintf(buf, sizeof(buf), "%s element: ", prefix); + mElement->dumpLOGV(buf); +} - if (mGL.mNorm.size) { - va->addLegacy(mGL.mNorm.type, - 3, - stride, - RS_KIND_NORMAL, - false, - mGL.mNorm.offset); - } +void Type::serialize(OStream *stream) const { + // Need to identify ourselves + stream->addU32((uint32_t)getClassId()); - if (mGL.mColor.size) { - va->addLegacy(mGL.mColor.type, - mGL.mColor.size, - stride, - RS_KIND_COLOR, - true, - mGL.mColor.offset); - } + String8 name(getName()); + stream->addString(&name); - if (mGL.mTex.size) { - va->addLegacy(mGL.mTex.type, - mGL.mTex.size, - stride, - RS_KIND_TEXTURE, - false, - mGL.mTex.offset); - } + mElement->serialize(stream); - if (mGL.mPointSize.size) { - va->addLegacy(mGL.mPointSize.type, - 1, - stride, - RS_KIND_POINT_SIZE, - false, - mGL.mPointSize.offset); - } + stream->addU32(mDimX); + stream->addU32(mDimY); + stream->addU32(mDimZ); + stream->addU8((uint8_t)(mDimLOD ? 1 : 0)); + stream->addU8((uint8_t)(mFaces ? 1 : 0)); } -void Type::enableGLVertexBuffer2(VertexArray *va) const -{ - // Do legacy buffers - enableGLVertexBuffer(va); - - uint32_t stride = mElement->getSizeBytes(); - for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) { - if (mGL.mUser[ct].size) { - va->addUser(mGL.mUser[ct], stride); - } +Type *Type::createFromStream(Context *rsc, IStream *stream) { + // First make sure we are reading the correct object + RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); + if (classID != RS_A3D_CLASS_ID_TYPE) { + LOGE("type loading skipped due to invalid class id\n"); + return NULL; } -} + String8 name; + stream->loadString(&name); + Element *elem = Element::createFromStream(rsc, stream); + if (!elem) { + return NULL; + } -void Type::dumpLOGV(const char *prefix) const -{ - char buf[1024]; - ObjectBase::dumpLOGV(prefix); - LOGV("%s Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces); - sprintf(buf, "%s element: ", prefix); - mElement->dumpLOGV(buf); + uint32_t x = stream->loadU32(); + uint32_t y = stream->loadU32(); + uint32_t z = stream->loadU32(); + uint8_t lod = stream->loadU8(); + uint8_t faces = stream->loadU8(); + return Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 ); } -bool Type::getIsNp2() const -{ +bool Type::getIsNp2() const { uint32_t x = getDimX(); uint32_t y = getDimY(); uint32_t z = getDimZ(); @@ -301,97 +209,99 @@ bool Type::getIsNp2() const return false; } - -////////////////////////////////////////////////// -// -namespace android { -namespace renderscript { - -void rsi_TypeBegin(Context *rsc, RsElement vse) -{ - TypeState * stc = &rsc->mStateType; - - stc->mX = 0; - stc->mY = 0; - stc->mZ = 0; - stc->mLOD = false; - stc->mFaces = false; - stc->mElement.set(static_cast<const Element *>(vse)); +bool Type::isEqual(const Type *other) const { + if (other == NULL) { + return false; + } + if (other->getElement()->isEqual(getElement()) && + other->getDimX() == mDimX && + other->getDimY() == mDimY && + other->getDimZ() == mDimZ && + other->getDimLOD() == mDimLOD && + other->getDimFaces() == mFaces) { + return true; + } + return false; } -void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value) -{ +Type * Type::getType(Context *rsc, const Element *e, + uint32_t dimX, uint32_t dimY, uint32_t dimZ, + bool dimLOD, bool dimFaces) { TypeState * stc = &rsc->mStateType; - if (dim < 0) { - //error - return; + ObjectBase::asyncLock(); + for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { + Type *t = stc->mTypes[ct]; + if (t->getElement() != e) continue; + if (t->getDimX() != dimX) continue; + if (t->getDimY() != dimY) continue; + if (t->getDimZ() != dimZ) continue; + if (t->getDimLOD() != dimLOD) continue; + if (t->getDimFaces() != dimFaces) continue; + t->incUserRef(); + ObjectBase::asyncUnlock(); + return t; } + ObjectBase::asyncUnlock(); - switch (dim) { - case RS_DIMENSION_X: - stc->mX = value; - return; - case RS_DIMENSION_Y: - stc->mY = value; - return; - case RS_DIMENSION_Z: - stc->mZ = value; - return; - case RS_DIMENSION_FACE: - stc->mFaces = (value != 0); - return; - case RS_DIMENSION_LOD: - stc->mLOD = (value != 0); - return; - default: - break; - } + Type *nt = new Type(rsc); + nt->mElement.set(e); + nt->mDimX = dimX; + nt->mDimY = dimY; + nt->mDimZ = dimZ; + nt->mDimLOD = dimLOD; + nt->mFaces = dimFaces; + nt->compute(); + nt->incUserRef(); + ObjectBase::asyncLock(); + stc->mTypes.push(nt); + ObjectBase::asyncUnlock(); - int32_t arrayNum = dim - RS_DIMENSION_ARRAY_0; - if ((dim < 0) || (dim > RS_DIMENSION_MAX)) { - LOGE("rsTypeAdd: Bad dimension"); - //error - return; - } + return nt; +} - // todo: implement array support +Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const { + return getType(rsc, mElement.get(), dimX, + mDimY, mDimZ, mDimLOD, mFaces); +} +Type * Type::cloneAndResize2D(Context *rsc, + uint32_t dimX, + uint32_t dimY) const { + return getType(rsc, mElement.get(), dimX, dimY, + mDimZ, mDimLOD, mFaces); } -RsType rsi_TypeCreate(Context *rsc) -{ - TypeState * stc = &rsc->mStateType; - for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) { - Type *t = stc->mTypes[ct]; - if (t->getElement() != stc->mElement.get()) continue; - if (t->getDimX() != stc->mX) continue; - if (t->getDimY() != stc->mY) continue; - if (t->getDimZ() != stc->mZ) continue; - if (t->getDimLOD() != stc->mLOD) continue; - if (t->getDimFaces() != stc->mFaces) continue; - t->incUserRef(); - return t; - } +////////////////////////////////////////////////// +// +namespace android { +namespace renderscript { - Type * st = new Type(rsc); - st->incUserRef(); - st->setDimX(stc->mX); - st->setDimY(stc->mY); - st->setDimZ(stc->mZ); - st->setElement(stc->mElement.get()); - st->setDimLOD(stc->mLOD); - st->setDimFaces(stc->mFaces); - st->compute(); - stc->mElement.clear(); - stc->mTypes.push(st); - return st; +} } +RsType rsaTypeCreate(RsContext con, 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; + // mDimLOD; mDimFaces; mElement; into typeData + Type *t = static_cast<Type *>(type); + + (*typeData++) = t->getDimX(); + (*typeData++) = t->getDimY(); + (*typeData++) = t->getDimZ(); + (*typeData++) = t->getDimLOD(); + (*typeData++) = t->getDimFaces() ? 1 : 0; + (*typeData++) = (uint32_t)t->getElement(); + t->getElement()->incUserRef(); +} diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h index c25577c..90ae039 100644 --- a/libs/rs/rsType.h +++ b/libs/rs/rsType.h @@ -25,15 +25,10 @@ namespace android { namespace renderscript { -class Type : public ObjectBase -{ +class Type : public ObjectBase { public: - Type(Context *); - virtual ~Type(); - Type * createTex2D(const Element *, size_t w, size_t h, bool mip); - size_t getOffsetForFace(uint32_t face) const; size_t getSizeBytes() const {return mTotalSizeBytes;} @@ -49,31 +44,33 @@ public: uint32_t getLODDimX(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mX;} uint32_t getLODDimY(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mY;} uint32_t getLODDimZ(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mZ;} - uint32_t getLODOffset(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mOffset;} + uint32_t getLODOffset(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mOffset;} uint32_t getLODOffset(uint32_t lod, uint32_t x) const; uint32_t getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const; uint32_t getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const; + uint32_t getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const; + uint32_t getLODCount() const {return mLODCount;} bool getIsNp2() const; - - void setElement(const Element *e) {mElement.set(e);} - void setDimX(uint32_t v) {mDimX = v;} - void setDimY(uint32_t v) {mDimY = v;} - void setDimZ(uint32_t v) {mDimZ = v;} - void setDimFaces(bool v) {mFaces = v;} - void setDimLOD(bool v) {mDimLOD = v;} - - void clear(); void compute(); - void enableGLVertexBuffer(class VertexArray *) const; - void enableGLVertexBuffer2(class VertexArray *) const; - void dumpLOGV(const char *prefix) const; + virtual void serialize(OStream *stream) const; + virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_TYPE; } + static Type *createFromStream(Context *rsc, IStream *stream); + + bool isEqual(const Type *other) const; + + Type * cloneAndResize1D(Context *rsc, uint32_t dimX) const; + Type * cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const; + + static Type * getType(Context *rsc, const Element *e, + uint32_t dimX, uint32_t dimY, uint32_t dimZ, + bool dimLOD, bool dimFaces); protected: struct LOD { @@ -101,10 +98,6 @@ protected: bool mDimLOD; bool mFaces; - // A list of array dimensions. The count is the number of array dimensions and the - // sizes is a per array size. - //Vector<size_t> mDimArraysSizes; - // count of mipmap levels, 0 indicates no mipmapping size_t mMipChainSizeBytes; @@ -112,18 +105,12 @@ protected: LOD *mLODs; uint32_t mLODCount; - struct GLState_t { - VertexArray::Attrib mUser[RS_MAX_ATTRIBS]; - VertexArray::Attrib mVtx; - VertexArray::Attrib mNorm; - VertexArray::Attrib mColor; - VertexArray::Attrib mTex; - VertexArray::Attrib mPointSize; - }; - GLState_t mGL; - void makeGLComponents(); +protected: + virtual void preDestroy(); + virtual ~Type(); private: + Type(Context *); Type(const Type &); }; @@ -133,14 +120,6 @@ public: TypeState(); ~TypeState(); - size_t mX; - size_t mY; - size_t mZ; - uint32_t mLOD; - bool mFaces; - ObjectBaseRef<const Element> mElement; - - // Cache of all existing types. Vector<Type *> mTypes; }; diff --git a/libs/rs/rsUtils.h b/libs/rs/rsUtils.h index 07f8933..0699b57 100644 --- a/libs/rs/rsUtils.h +++ b/libs/rs/rsUtils.h @@ -19,15 +19,23 @@ #define LOG_NDEBUG 0 #define LOG_TAG "RenderScript" + #include <utils/Log.h> -#include <utils/Vector.h> -#include <utils/KeyedVector.h> + +#include "rsStream.h" + #include <utils/String8.h> +#include <utils/Vector.h> + #include <stdlib.h> #include <pthread.h> #include <time.h> +#include <cutils/atomic.h> +#ifndef ANDROID_RS_BUILD_FOR_HOST #include <EGL/egl.h> +#endif + #include <math.h> #include "RenderScript.h" @@ -36,11 +44,31 @@ namespace android { namespace renderscript { #if 1 -#define rsAssert(v) do {if(!(v)) LOGE("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__);} while(0) +#define rsAssert(v) do {if(!(v)) LOGE("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__);} while (0) #else -#define rsAssert(v) while(0) +#define rsAssert(v) while (0) #endif +typedef float rsvF_2 __attribute__ ((vector_size (8))); +typedef float rsvF_4 __attribute__ ((vector_size (16))); +typedef uint8_t rsvU8_4 __attribute__ ((vector_size (4))); + +union float2 { + rsvF_2 v; + float f[2]; +}; + +union float4 { + rsvF_4 v; + float f[4]; +}; + +union uchar4 { + rsvU8_4 v; + uint8_t f[4]; + uint32_t packed; +}; + template<typename T> T rsMin(T in1, T in2) { @@ -51,8 +79,7 @@ T rsMin(T in1, T in2) } template<typename T> -T rsMax(T in1, T in2) -{ +T rsMax(T in1, T in2) { if (in1 < in2) { return in2; } @@ -60,10 +87,9 @@ T rsMax(T in1, T in2) } template<typename T> -T rsFindHighBit(T val) -{ +T rsFindHighBit(T val) { uint32_t bit = 0; - while(val > 1) { + while (val > 1) { bit++; val>>=1; } @@ -71,14 +97,12 @@ T rsFindHighBit(T val) } template<typename T> -bool rsIsPow2(T val) -{ +bool rsIsPow2(T val) { return (val & (val-1)) == 0; } template<typename T> -T rsHigherPow2(T v) -{ +T rsHigherPow2(T v) { if (rsIsPow2(v)) { return v; } @@ -86,17 +110,14 @@ T rsHigherPow2(T v) } template<typename T> -T rsLowerPow2(T v) -{ +T rsLowerPow2(T v) { if (rsIsPow2(v)) { return v; } return 1 << rsFindHighBit(v); } - -static inline uint16_t rs888to565(uint32_t r, uint32_t g, uint32_t b) -{ +static inline uint16_t rs888to565(uint32_t r, uint32_t g, uint32_t b) { uint16_t t = 0; t |= b >> 3; t |= (g >> 2) << 5; @@ -104,16 +125,14 @@ static inline uint16_t rs888to565(uint32_t r, uint32_t g, uint32_t b) return t; } -static inline uint16_t rsBoxFilter565(uint16_t i1, uint16_t i2, uint16_t i3, uint16_t i4) -{ +static inline uint16_t rsBoxFilter565(uint16_t i1, uint16_t i2, uint16_t i3, uint16_t i4) { uint32_t r = ((i1 & 0x1f) + (i2 & 0x1f) + (i3 & 0x1f) + (i4 & 0x1f)); uint32_t g = ((i1 >> 5) & 0x3f) + ((i2 >> 5) & 0x3f) + ((i3 >> 5) & 0x3f) + ((i4 >> 5) & 0x3f); uint32_t b = ((i1 >> 11) + (i2 >> 11) + (i3 >> 11) + (i4 >> 11)); return (r >> 2) | ((g >> 2) << 5) | ((b >> 2) << 11); } -static inline uint32_t rsBoxFilter8888(uint32_t i1, uint32_t i2, uint32_t i3, uint32_t i4) -{ +static inline uint32_t rsBoxFilter8888(uint32_t i1, uint32_t i2, uint32_t i3, uint32_t i4) { uint32_t r = (i1 & 0xff) + (i2 & 0xff) + (i3 & 0xff) + (i4 & 0xff); uint32_t g = ((i1 >> 8) & 0xff) + ((i2 >> 8) & 0xff) + ((i3 >> 8) & 0xff) + ((i4 >> 8) & 0xff); uint32_t b = ((i1 >> 16) & 0xff) + ((i2 >> 16) & 0xff) + ((i3 >> 16) & 0xff) + ((i4 >> 16) & 0xff); @@ -121,8 +140,6 @@ static inline uint32_t rsBoxFilter8888(uint32_t i1, uint32_t i2, uint32_t i3, ui return (r >> 2) | ((g >> 2) << 8) | ((b >> 2) << 16) | ((a >> 2) << 24); } - - } } diff --git a/libs/rs/rsVertexArray.cpp b/libs/rs/rsVertexArray.cpp index 6c2002d..d9393fe 100644 --- a/libs/rs/rsVertexArray.cpp +++ b/libs/rs/rsVertexArray.cpp @@ -14,206 +14,119 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" - #include <GLES/gl.h> #include <GLES2/gl2.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#endif using namespace android; using namespace android::renderscript; - -VertexArray::VertexArray() -{ - clearAll(); +VertexArray::VertexArray(const Attrib *attribs, uint32_t numAttribs) { + mAttribs = attribs; + mCount = numAttribs; } -VertexArray::~VertexArray() -{ +VertexArray::~VertexArray() { } - -void VertexArray::clearAll() -{ - for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) { - mAttribs[ct].clear(); - } - mActiveBuffer = 0; - mCount = 0; -} - -VertexArray::Attrib::Attrib() -{ +VertexArray::Attrib::Attrib() { clear(); } -void VertexArray::Attrib::set(const Attrib &a) -{ - buffer = a.buffer; - offset = a.offset; - type = a.type; - size = a.size; - stride = a.stride; - normalized = a.normalized; - kind = RS_KIND_USER; - name.setTo(a.name); -} - -void VertexArray::Attrib::clear() -{ +void VertexArray::Attrib::clear() { buffer = 0; offset = 0; type = 0; size = 0; stride = 0; + ptr = NULL; normalized = false; name.setTo(""); } -void VertexArray::clear(uint32_t n) -{ - mAttribs[n].clear(); -} - -void VertexArray::addUser(const Attrib &a, uint32_t stride) -{ - assert(mCount < RS_MAX_ATTRIBS); - mAttribs[mCount].set(a); - mAttribs[mCount].buffer = mActiveBuffer; - mAttribs[mCount].stride = stride; - mAttribs[mCount].kind = RS_KIND_USER; - mCount ++; -} - -void VertexArray::addLegacy(uint32_t type, uint32_t size, uint32_t stride, RsDataKind kind, bool normalized, uint32_t offset) -{ - assert(mCount < RS_MAX_ATTRIBS); - mAttribs[mCount].clear(); - mAttribs[mCount].type = type; - mAttribs[mCount].size = size; - mAttribs[mCount].offset = offset; - mAttribs[mCount].normalized = normalized; - mAttribs[mCount].buffer = mActiveBuffer; - mAttribs[mCount].stride = stride; - mAttribs[mCount].kind = kind; - mCount ++; +void VertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride, + bool normalized, uint32_t offset, + const char *name) { + clear(); + this->type = type; + this->size = size; + this->offset = offset; + this->normalized = normalized; + this->stride = stride; + this->name.setTo(name); } void VertexArray::logAttrib(uint32_t idx, uint32_t slot) const { - LOGE("va %i: slot=%i name=%s buf=%i size=%i type=0x%x kind=%i stride=0x%x norm=%i offset=0x%x", idx, slot, + if (idx == 0) { + LOGV("Starting vertex attribute binding"); + } + LOGV("va %i: slot=%i name=%s buf=%i ptr=%p size=%i type=0x%x stride=0x%x norm=%i offset=0x%x", + idx, slot, mAttribs[idx].name.string(), mAttribs[idx].buffer, + mAttribs[idx].ptr, mAttribs[idx].size, mAttribs[idx].type, - mAttribs[idx].kind, mAttribs[idx].stride, mAttribs[idx].normalized, mAttribs[idx].offset); } -void VertexArray::setupGL(const Context *rsc, class VertexArrayState *state) const -{ - glClientActiveTexture(GL_TEXTURE0); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_POINT_SIZE_ARRAY_OES); - - for (uint32_t ct=0; ct < mCount; ct++) { - switch(mAttribs[ct].kind) { - case RS_KIND_POSITION: - //logAttrib(POSITION); - glEnableClientState(GL_VERTEX_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer); - glVertexPointer(mAttribs[ct].size, - mAttribs[ct].type, - mAttribs[ct].stride, - (void *)mAttribs[ct].offset); - break; - - case RS_KIND_NORMAL: - //logAttrib(NORMAL); - glEnableClientState(GL_NORMAL_ARRAY); - rsAssert(mAttribs[ct].size == 3); - glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer); - glNormalPointer(mAttribs[ct].type, - mAttribs[ct].stride, - (void *)mAttribs[ct].offset); - break; - - case RS_KIND_COLOR: - //logAttrib(COLOR); - glEnableClientState(GL_COLOR_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer); - glColorPointer(mAttribs[ct].size, - mAttribs[ct].type, - mAttribs[ct].stride, - (void *)mAttribs[ct].offset); - break; - - case RS_KIND_TEXTURE: - //logAttrib(TEXTURE); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer); - glTexCoordPointer(mAttribs[ct].size, - mAttribs[ct].type, - mAttribs[ct].stride, - (void *)mAttribs[ct].offset); - break; - - case RS_KIND_POINT_SIZE: - //logAttrib(POINT_SIZE); - glEnableClientState(GL_POINT_SIZE_ARRAY_OES); - glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer); - glPointSizePointerOES(mAttribs[ct].type, - mAttribs[ct].stride, - (void *)mAttribs[ct].offset); - break; - - default: - rsAssert(0); - } - } - - rsc->checkError("VertexArray::setupGL"); -} - -void VertexArray::setupGL2(const Context *rsc, class VertexArrayState *state, ShaderCache *sc) const -{ +void VertexArray::setupGL2(const Context *rsc, + class VertexArrayState *state, + ShaderCache *sc) const { rsc->checkError("VertexArray::setupGL2 start"); - for (uint32_t ct=1; ct <= state->mLastEnableCount; ct++) { - glDisableVertexAttribArray(ct); + uint32_t maxAttrs = state->mAttrsEnabledSize; + for (uint32_t ct=1; ct < maxAttrs; ct++) { + if(state->mAttrsEnabled[ct]) { + glDisableVertexAttribArray(ct); + state->mAttrsEnabled[ct] = false; + } } rsc->checkError("VertexArray::setupGL2 disabled"); for (uint32_t ct=0; ct < mCount; ct++) { - uint32_t slot = 0; - if (sc->isUserVertexProgram()) { - slot = sc->vtxAttribSlot(ct); - } else { - if (mAttribs[ct].kind == RS_KIND_USER) { - continue; - } - slot = sc->vtxAttribSlot(mAttribs[ct].kind); + int32_t slot = sc->vtxAttribSlot(mAttribs[ct].name); + if (rsc->props.mLogShadersAttr) { + logAttrib(ct, slot); + } + if (slot < 0 || slot >= (int32_t)maxAttrs) { + continue; } - - //logAttrib(ct, slot); glEnableVertexAttribArray(slot); + state->mAttrsEnabled[slot] = true; glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer); - glVertexAttribPointer(slot, mAttribs[ct].size, mAttribs[ct].type, mAttribs[ct].normalized, mAttribs[ct].stride, - (void *)mAttribs[ct].offset); + mAttribs[ct].ptr + mAttribs[ct].offset); } - state->mLastEnableCount = mCount; rsc->checkError("VertexArray::setupGL2 done"); } //////////////////////////////////////////// +VertexArrayState::VertexArrayState() { + mAttrsEnabled = NULL; + mAttrsEnabledSize = 0; +} -void VertexArrayState::init(Context *) { - mLastEnableCount = 0; +VertexArrayState::~VertexArrayState() { + if (mAttrsEnabled) { + delete[] mAttrsEnabled; + mAttrsEnabled = NULL; + } +} +void VertexArrayState::init(Context *rsc) { + mAttrsEnabledSize = rsc->getMaxVertexAttributes(); + 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/rsVertexArray.h index 3904cb6..45d9e82 100644 --- a/libs/rs/rsVertexArray.h +++ b/libs/rs/rsVertexArray.h @@ -27,60 +27,54 @@ namespace renderscript { class ShaderCache; // An element is a group of Components that occupies one cell in a structure. -class VertexArray -{ +class VertexArray { public: - VertexArray(); - virtual ~VertexArray(); - - class Attrib { public: uint32_t buffer; + const uint8_t * ptr; uint32_t offset; uint32_t type; uint32_t size; uint32_t stride; bool normalized; String8 name; - RsDataKind kind; Attrib(); - void set(const 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(); - void clearAll(); - void setActiveBuffer(uint32_t id) {mActiveBuffer = id;} - void addUser(const Attrib &, uint32_t stride); - void addLegacy(uint32_t type, uint32_t size, uint32_t stride, RsDataKind kind, bool normalized, uint32_t offset); - - void setupGL(const Context *rsc, class VertexArrayState *) const; void setupGL2(const Context *rsc, class VertexArrayState *, ShaderCache *) const; void logAttrib(uint32_t idx, uint32_t slot) const; protected: void clear(uint32_t index); uint32_t mActiveBuffer; + const uint8_t * mActivePointer; uint32_t mCount; - Attrib mAttribs[RS_MAX_ATTRIBS]; + const Attrib *mAttribs; }; class VertexArrayState { public: + VertexArrayState(); + ~VertexArrayState(); void init(Context *); - uint32_t mLastEnableCount; - //VertexArray::Attrib mAttribs[VertexArray::_LAST]; + bool *mAttrsEnabled; + uint32_t mAttrsEnabledSize; }; } } -#endif //ANDROID_LIGHT_H +#endif //ANDROID_VERTEX_ARRAY_H diff --git a/libs/rs/rsg_ScriptJavaClass.cpp b/libs/rs/rsg_ScriptJavaClass.cpp deleted file mode 100644 index cee9f52..0000000 --- a/libs/rs/rsg_ScriptJavaClass.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#define NO_RS_FUNCS 1 - -#include "stdio.h" -#include "RenderScript.h" -#include <vector> - -struct Element; - -struct ElementField { - const char *name; - Element *e; - ElementField(const char *n, Element *_e) { - name = n; - e = _e; - } - ElementField() { - name = NULL; - e = NULL; - } -}; - -struct Element { - ElementField *fields; - size_t fieldCount; - const char *name; - bool generated; - - RsDataType compType; - uint32_t compVectorSize; - - Element() { - fields = NULL; - fieldCount = 0; - name = NULL; - generated = false; - compType = RS_TYPE_ELEMENT; - compVectorSize = 0; - } - - Element(uint32_t _fieldCount, const char *_name) { - fields = new ElementField[_fieldCount]; - fieldCount = _fieldCount; - name = _name; - generated = false; - compType = RS_TYPE_ELEMENT; - compVectorSize = 0; - } - - Element(RsDataType t, uint32_t s) { - fields = NULL; - fieldCount = 0; - name = NULL; - generated = false; - compType = t; - compVectorSize = s; - } - -}; - - -static void genHeader(FILE *f, const char *packageName) -{ - fprintf(f, "package %s;\n", packageName); - fprintf(f, "\n"); - fprintf(f, "import android.renderscript.*;\n"); - fprintf(f, "\n"); - fprintf(f, "\n"); -} - -static const char * RSTypeToJava(RsDataType dt) -{ - switch(dt) { - //case RS_TYPE_FLOAT_16: return "float"; - case RS_TYPE_FLOAT_32: return "float"; - //case RS_TYPE_FLOAT_64: return "double"; - - case RS_TYPE_SIGNED_8: return "byte"; - case RS_TYPE_SIGNED_16: return "short"; - case RS_TYPE_SIGNED_32: return "int"; - //case RS_TYPE_SIGNED_64: return "long"; - - case RS_TYPE_UNSIGNED_8: return "short"; - case RS_TYPE_UNSIGNED_16: return "int"; - case RS_TYPE_UNSIGNED_32: return "long"; - //case RS_TYPE_UNSIGNED_64: return NULL; - - //case RS_TYPE_ELEMENT: return "android.renderscript.Element"; - //case RS_TYPE_TYPE: return "android.renderscript.Type"; - //case RS_TYPE_ALLOCATION: return "android.renderscript.Allocation"; - //case RS_TYPE_SAMPLER: return "android.renderscript.Sampler"; - //case RS_TYPE_SCRIPT: return "android.renderscript.Script"; - //case RS_TYPE_MESH: return "android.renderscript.Mesh"; - //case RS_TYPE_PROGRAM_FRAGMENT: return "android.renderscript.ProgramFragment"; - //case RS_TYPE_PROGRAM_VERTEX: return "android.renderscript.ProgramVertex"; - //case RS_TYPE_PROGRAM_RASTER: return "android.renderscript.ProgramRaster"; - //case RS_TYPE_PROGRAM_STORE: return "android.renderscript.ProgramStore"; - default: return NULL; - } - return NULL; -} - -static const char * RSTypeToString(RsDataType dt) -{ - switch(dt) { - case RS_TYPE_FLOAT_16: return "F16"; - case RS_TYPE_FLOAT_32: return "F32"; - case RS_TYPE_FLOAT_64: return "F64"; - - case RS_TYPE_SIGNED_8: return "I8"; - case RS_TYPE_SIGNED_16: return "I16"; - case RS_TYPE_SIGNED_32: return "I32"; - case RS_TYPE_SIGNED_64: return "I64"; - - case RS_TYPE_UNSIGNED_8: return "U8"; - case RS_TYPE_UNSIGNED_16: return "U16"; - case RS_TYPE_UNSIGNED_32: return "U32"; - case RS_TYPE_UNSIGNED_64: return "U64"; - - //case RS_TYPE_ELEMENT: return "android.renderscript.Element"; - //case RS_TYPE_TYPE: return "android.renderscript.Type"; - //case RS_TYPE_ALLOCATION: return "android.renderscript.Allocation"; - //case RS_TYPE_SAMPLER: return "android.renderscript.Sampler"; - //case RS_TYPE_SCRIPT: return "android.renderscript.Script"; - //case RS_TYPE_MESH: return "android.renderscript.Mesh"; - //case RS_TYPE_PROGRAM_FRAGMENT: return "android.renderscript.ProgramFragment"; - //case RS_TYPE_PROGRAM_VERTEX: return "android.renderscript.ProgramVertex"; - //case RS_TYPE_PROGRAM_RASTER: return "android.renderscript.ProgramRaster"; - //case RS_TYPE_PROGRAM_STORE: return "android.renderscript.ProgramStore"; - default: return NULL; - } - return NULL; -} - -bool rsGenerateElementClass(const Element *e, const char *packageName, FILE *f) -{ - genHeader(f, packageName); - - fprintf(f, "class Element_%s {\n", e->name); - - for (size_t ct=0; ct < e->fieldCount; ct++) { - const char *ts = RSTypeToJava(e->fields[ct].e->compType); - if (ts == NULL) { - return false; - } - fprintf(f, " public %s %s;\n", ts, e->fields[ct].name); - } - - fprintf(f, "\n"); - fprintf(f, " static Element getElement(RenderScript rs) {\n"); - fprintf(f, " Element.Builder eb = new Element.Builder(rs);\n"); - for (size_t ct=0; ct < e->fieldCount; ct++) { - const char *ts = RSTypeToString(e->fields[ct].e->compType); - fprintf(f, " eb.add(Element.USER_%s(rs), \"%s\");\n", ts, e->fields[ct].name); - } - fprintf(f, " return eb.create();\n"); - fprintf(f, " }\n"); - - fprintf(f, " static Allocation createAllocation(RenderScript rs) {\n"); - fprintf(f, " Element e = getElement(rs);\n"); - fprintf(f, " Allocation a = Allocation.createSized(rs, e, 1);\n"); - fprintf(f, " return a;\n"); - fprintf(f, " }\n"); - - - fprintf(f, " void copyToAllocation(Allocation a) {\n"); - fprintf(f, " mIOBuffer.reset();\n"); - for (size_t ct=0; ct < e->fieldCount; ct++) { - const char *ts = RSTypeToString(e->fields[ct].e->compType); - fprintf(f, " mIOBuffer.add%s(%s);\n", ts, e->fields[ct].name); - } - fprintf(f, " a.data(mIOBuffer.getData());\n"); - fprintf(f, " }\n"); - - - - fprintf(f, " private FieldPacker mIOBuffer[];\n"); - fprintf(f, " public Element_%s() {\n", e->name); - fprintf(f, " mIOBuffer = new FieldPacker(%i);\n", 100/*element->getSizeBytes()*/); - fprintf(f, " }\n"); - - - fprintf(f, "}\n"); - - return true; -} - -bool rsGenerateElementClassFile(Element *e, const char *packageName) -{ - char buf[1024]; - sprintf(buf, "Element_%s.java", e->name); - printf("Creating file %s \n", buf); - FILE *f = fopen(buf, "w"); - bool ret = rsGenerateElementClass(e, packageName, f); - fclose(f); - return ret; -} - - - - -/* -bool rsGenerateScriptClass(const ScriptC *script, const char *packageName, FILE *f) -{ - genHeader(f, packageName); - - fprintf(f, "class ScriptC_%s {\n", script->getName()); - - - - ObjectBaseRef<const Type> mTypes[MAX_SCRIPT_BANKS]; - String8 mSlotNames[MAX_SCRIPT_BANKS]; - bool mSlotWritable[MAX_SCRIPT_BANKS]; - - -} -*/ - - - -int main(int argc, const char *argv) -{ - Element *u8 = new Element(RS_TYPE_UNSIGNED_8, 1); - Element *i32 = new Element(RS_TYPE_SIGNED_32, 1); - Element *f32 = new Element(RS_TYPE_FLOAT_32, 1); - - Element *e_Pixel = new Element(4, "Pixel"); - e_Pixel->fields[0].e = u8; - e_Pixel->fields[0].name = "a"; - e_Pixel->fields[1].e = u8; - e_Pixel->fields[1].name = "b"; - e_Pixel->fields[2].e = u8; - e_Pixel->fields[2].name = "g"; - e_Pixel->fields[3].e = u8; - e_Pixel->fields[3].name = "r"; - - Element *e_Params = new Element(5, "Params"); - e_Params->fields[0].e = i32; - e_Params->fields[0].name = "inHeight"; - e_Params->fields[1].e = i32; - e_Params->fields[1].name = "inWidth"; - e_Params->fields[2].e = i32; - e_Params->fields[2].name = "outHeight"; - e_Params->fields[3].e = i32; - e_Params->fields[3].name = "outWidth"; - e_Params->fields[4].e = f32; - e_Params->fields[4].name = "threshold"; - - - printf("1\n"); - rsGenerateElementClassFile(e_Pixel, "android"); - rsGenerateElementClassFile(e_Params, "android"); - -} - diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c index f4e8c68..4ac5b7f 100644 --- a/libs/rs/rsg_generator.c +++ b/libs/rs/rsg_generator.c @@ -2,8 +2,7 @@ #include "spec.h" #include <stdio.h> -void printFileHeader(FILE *f) -{ +void printFileHeader(FILE *f) { fprintf(f, "/*\n"); fprintf(f, " * Copyright (C) 2010 The Android Open Source Project\n"); fprintf(f, " *\n"); @@ -21,14 +20,13 @@ void printFileHeader(FILE *f) fprintf(f, " */\n\n"); } -void printVarType(FILE *f, const VarType *vt) -{ +void printVarType(FILE *f, const VarType *vt) { int ct; if (vt->isConst) { fprintf(f, "const "); } - switch(vt->type) { + switch (vt->type) { case 0: fprintf(f, "void"); break; @@ -49,22 +47,21 @@ void printVarType(FILE *f, const VarType *vt) break; } - if(vt->ptrLevel) { + if (vt->ptrLevel) { fprintf(f, " "); - for(ct=0; ct < vt->ptrLevel; ct++) { + for (ct=0; ct < vt->ptrLevel; ct++) { fprintf(f, "*"); } } - if(vt->name[0]) { + if (vt->name[0]) { fprintf(f, " %s", vt->name); } } -void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) -{ +void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) { int ct; - for(ct=0; ct < api->paramCount; ct++) { + for (ct=0; ct < api->paramCount; ct++) { if (ct || assumePrevious) { fprintf(f, ", "); } @@ -72,23 +69,22 @@ void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) } } -void printStructures(FILE *f) -{ +void printStructures(FILE *f) { int ct; int ct2; - for(ct=0; ct < apiCount; ct++) { + for (ct=0; ct < apiCount; ct++) { fprintf(f, "typedef struct RS_CMD_%s_rec RS_CMD_%s;\n", apis[ct].name, apis[ct].name); } fprintf(f, "\n"); - for(ct=0; ct < apiCount; ct++) { + for (ct=0; ct < apiCount; ct++) { const ApiEntry * api = &apis[ct]; fprintf(f, "#define RS_CMD_ID_%s %i\n", api->name, ct+1); fprintf(f, "struct RS_CMD_%s_rec {\n", api->name); //fprintf(f, " RsCommandHeader _hdr;\n"); - for(ct2=0; ct2 < api->paramCount; ct2++) { + for (ct2=0; ct2 < api->paramCount; ct2++) { fprintf(f, " "); printVarType(f, &api->params[ct2]); fprintf(f, ";\n"); @@ -97,8 +93,7 @@ void printStructures(FILE *f) } } -void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext) -{ +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) { @@ -110,26 +105,23 @@ void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addCont fprintf(f, ")"); } -void printFuncDecls(FILE *f, const char *prefix, int addContext) -{ +void printFuncDecls(FILE *f, const char *prefix, int addContext) { int ct; - for(ct=0; ct < apiCount; ct++) { + for (ct=0; ct < apiCount; ct++) { printFuncDecl(f, &apis[ct], prefix, addContext); fprintf(f, ";\n"); } fprintf(f, "\n\n"); } -void printPlaybackFuncs(FILE *f, const char *prefix) -{ +void printPlaybackFuncs(FILE *f, const char *prefix) { int ct; - for(ct=0; ct < apiCount; ct++) { + for (ct=0; ct < apiCount; ct++) { fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name); } } -void printApiCpp(FILE *f) -{ +void printApiCpp(FILE *f) { int ct; int ct2; @@ -144,7 +136,7 @@ void printApiCpp(FILE *f) fprintf(f, "#include \"rsHandcode.h\"\n"); fprintf(f, "\n"); - for(ct=0; ct < apiCount; ct++) { + for (ct=0; ct < apiCount; ct++) { int needFlush = 0; const ApiEntry * api = &apis[ct]; @@ -152,7 +144,7 @@ void printApiCpp(FILE *f) fprintf(f, "\n{\n"); if (api->handcodeApi) { fprintf(f, " rsHCAPI_%s(rsc", api->name); - for(ct2=0; ct2 < api->paramCount; ct2++) { + for (ct2=0; ct2 < api->paramCount; ct2++) { const VarType *vt = &api->params[ct2]; fprintf(f, ", %s", vt->name); } @@ -163,7 +155,7 @@ void printApiCpp(FILE *f) 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); - for(ct2=0; ct2 < api->paramCount; ct2++) { + 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); @@ -188,8 +180,7 @@ void printApiCpp(FILE *f) } } -void printPlaybackCpp(FILE *f) -{ +void printPlaybackCpp(FILE *f) { int ct; int ct2; @@ -204,7 +195,7 @@ void printPlaybackCpp(FILE *f) fprintf(f, "#include \"rsHandcode.h\"\n"); fprintf(f, "\n"); - for(ct=0; ct < apiCount; ct++) { + for (ct=0; ct < apiCount; ct++) { const ApiEntry * api = &apis[ct]; fprintf(f, "void rsp_%s(Context *con, const void *vp)\n", api->name); @@ -219,7 +210,7 @@ void printPlaybackCpp(FILE *f) fprintf(f, "con->mIO.mToCoreRet = (intptr_t)"); } fprintf(f, "rsi_%s(con", api->name); - for(ct2=0; ct2 < api->paramCount; ct2++) { + for (ct2=0; ct2 < api->paramCount; ct2++) { const VarType *vt = &api->params[ct2]; fprintf(f, ",\n cmd->%s", vt->name); } @@ -228,9 +219,9 @@ void printPlaybackCpp(FILE *f) fprintf(f, "};\n\n"); } - fprintf(f, "RsPlaybackFunc gPlaybackFuncs[] = {\n"); + fprintf(f, "RsPlaybackFunc gPlaybackFuncs[%i] = {\n", apiCount + 1); fprintf(f, " NULL,\n"); - for(ct=0; ct < apiCount; ct++) { + for (ct=0; ct < apiCount; ct++) { fprintf(f, " %s%s,\n", "rsp_", apis[ct].name); } fprintf(f, "};\n"); @@ -239,8 +230,7 @@ void printPlaybackCpp(FILE *f) fprintf(f, "};\n"); } -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { if (argc != 3) { fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]); return 1; @@ -263,7 +253,7 @@ int main(int argc, char **argv) FILE *f = fopen(outFile, "w"); printFileHeader(f); - switch(choice) { + switch (choice) { case '0': // rsgApiStructs.h { fprintf(f, "\n"); @@ -275,7 +265,7 @@ int main(int argc, char **argv) printFuncDecls(f, "rsi_", 1); printPlaybackFuncs(f, "rsp_"); fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *);\n"); - fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[];\n"); + fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[%i];\n", apiCount + 1); fprintf(f, "}\n"); fprintf(f, "}\n"); diff --git a/libs/rs/scriptc/rs_cl.rsh b/libs/rs/scriptc/rs_cl.rsh new file mode 100644 index 0000000..d78e62e --- /dev/null +++ b/libs/rs/scriptc/rs_cl.rsh @@ -0,0 +1,449 @@ +#ifndef __RS_CL_RSH__ +#define __RS_CL_RSH__ + +#define _RS_RUNTIME extern + +// Conversions +#define CVT_FUNC_2(typeout, typein) \ +_RS_RUNTIME typeout##2 __attribute__((overloadable)) \ + convert_##typeout##2(typein##2 v); \ +_RS_RUNTIME typeout##3 __attribute__((overloadable)) \ + convert_##typeout##3(typein##3 v); \ +_RS_RUNTIME typeout##4 __attribute__((overloadable)) \ + convert_##typeout##4(typein##4 v); + + +#define CVT_FUNC(type) CVT_FUNC_2(type, uchar) \ + CVT_FUNC_2(type, char) \ + CVT_FUNC_2(type, ushort) \ + CVT_FUNC_2(type, short) \ + CVT_FUNC_2(type, uint) \ + CVT_FUNC_2(type, int) \ + CVT_FUNC_2(type, float) + +CVT_FUNC(char) +CVT_FUNC(uchar) +CVT_FUNC(short) +CVT_FUNC(ushort) +CVT_FUNC(int) +CVT_FUNC(uint) +CVT_FUNC(float) + +// Float ops, 6.11.2 + +#define FN_FUNC_FN(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) fnc(float2 v); \ +_RS_RUNTIME float3 __attribute__((overloadable)) fnc(float3 v); \ +_RS_RUNTIME float4 __attribute__((overloadable)) fnc(float4 v); + +#define IN_FUNC_FN(fnc) \ +_RS_RUNTIME int2 __attribute__((overloadable)) fnc(float2 v); \ +_RS_RUNTIME int3 __attribute__((overloadable)) fnc(float3 v); \ +_RS_RUNTIME int4 __attribute__((overloadable)) fnc(float4 v); + +#define FN_FUNC_FN_FN(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) fnc(float2 v1, float2 v2); \ +_RS_RUNTIME float3 __attribute__((overloadable)) fnc(float3 v1, float3 v2); \ +_RS_RUNTIME float4 __attribute__((overloadable)) fnc(float4 v1, float4 v2); + +#define FN_FUNC_FN_F(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) fnc(float2 v1, float v2); \ +_RS_RUNTIME float3 __attribute__((overloadable)) fnc(float3 v1, float v2); \ +_RS_RUNTIME float4 __attribute__((overloadable)) fnc(float4 v1, float v2); + +#define FN_FUNC_FN_IN(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) fnc(float2 v1, int2 v2); \ +_RS_RUNTIME float3 __attribute__((overloadable)) fnc(float3 v1, int3 v2); \ +_RS_RUNTIME float4 __attribute__((overloadable)) fnc(float4 v1, int4 v2); \ + +#define FN_FUNC_FN_I(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) fnc(float2 v1, int v2); \ +_RS_RUNTIME float3 __attribute__((overloadable)) fnc(float3 v1, int v2); \ +_RS_RUNTIME float4 __attribute__((overloadable)) fnc(float4 v1, int v2); + +#define FN_FUNC_FN_PFN(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) \ + fnc(float2 v1, float2 *v2); \ +_RS_RUNTIME float3 __attribute__((overloadable)) \ + fnc(float3 v1, float3 *v2); \ +_RS_RUNTIME float4 __attribute__((overloadable)) \ + fnc(float4 v1, float4 *v2); + +#define FN_FUNC_FN_PIN(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) fnc(float2 v1, int2 *v2); \ +_RS_RUNTIME float3 __attribute__((overloadable)) fnc(float3 v1, int3 *v2); \ +_RS_RUNTIME float4 __attribute__((overloadable)) fnc(float4 v1, int4 *v2); + +#define FN_FUNC_FN_FN_FN(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) \ + fnc(float2 v1, float2 v2, float2 v3); \ +_RS_RUNTIME float3 __attribute__((overloadable)) \ + fnc(float3 v1, float3 v2, float3 v3); \ +_RS_RUNTIME float4 __attribute__((overloadable)) \ + fnc(float4 v1, float4 v2, float4 v3); + +#define FN_FUNC_FN_FN_PIN(fnc) \ +_RS_RUNTIME float2 __attribute__((overloadable)) \ + fnc(float2 v1, float2 v2, int2 *v3); \ +_RS_RUNTIME float3 __attribute__((overloadable)) \ + fnc(float3 v1, float3 v2, int3 *v3); \ +_RS_RUNTIME float4 __attribute__((overloadable)) \ + fnc(float4 v1, float4 v2, int4 *v3); + + +extern float __attribute__((overloadable)) acos(float); +FN_FUNC_FN(acos) + +extern float __attribute__((overloadable)) acosh(float); +FN_FUNC_FN(acosh) + +_RS_RUNTIME float __attribute__((overloadable)) acospi(float v); + + +FN_FUNC_FN(acospi) + +extern float __attribute__((overloadable)) asin(float); +FN_FUNC_FN(asin) + +extern float __attribute__((overloadable)) asinh(float); +FN_FUNC_FN(asinh) + + +_RS_RUNTIME float __attribute__((overloadable)) asinpi(float v); +FN_FUNC_FN(asinpi) + +extern float __attribute__((overloadable)) atan(float); +FN_FUNC_FN(atan) + +extern float __attribute__((overloadable)) atan2(float, float); +FN_FUNC_FN_FN(atan2) + +extern float __attribute__((overloadable)) atanh(float); +FN_FUNC_FN(atanh) + + +_RS_RUNTIME float __attribute__((overloadable)) atanpi(float v); +FN_FUNC_FN(atanpi) + + +_RS_RUNTIME float __attribute__((overloadable)) atan2pi(float y, float x); +FN_FUNC_FN_FN(atan2pi) + +extern float __attribute__((overloadable)) cbrt(float); +FN_FUNC_FN(cbrt) + +extern float __attribute__((overloadable)) ceil(float); +FN_FUNC_FN(ceil) + +extern float __attribute__((overloadable)) copysign(float, float); +FN_FUNC_FN_FN(copysign) + +extern float __attribute__((overloadable)) cos(float); +FN_FUNC_FN(cos) + +extern float __attribute__((overloadable)) cosh(float); +FN_FUNC_FN(cosh) + + +_RS_RUNTIME float __attribute__((overloadable)) cospi(float v); +FN_FUNC_FN(cospi) + +extern float __attribute__((overloadable)) erfc(float); +FN_FUNC_FN(erfc) + +extern float __attribute__((overloadable)) erf(float); +FN_FUNC_FN(erf) + +extern float __attribute__((overloadable)) exp(float); +FN_FUNC_FN(exp) + +extern float __attribute__((overloadable)) exp2(float); +FN_FUNC_FN(exp2) + +extern float __attribute__((overloadable)) pow(float, float); + +_RS_RUNTIME float __attribute__((overloadable)) exp10(float v); +FN_FUNC_FN(exp10) + +extern float __attribute__((overloadable)) expm1(float); +FN_FUNC_FN(expm1) + +extern float __attribute__((overloadable)) fabs(float); +FN_FUNC_FN(fabs) + +extern float __attribute__((overloadable)) fdim(float, float); +FN_FUNC_FN_FN(fdim) + +extern float __attribute__((overloadable)) floor(float); +FN_FUNC_FN(floor) + +extern float __attribute__((overloadable)) fma(float, float, float); +FN_FUNC_FN_FN_FN(fma) + +extern float __attribute__((overloadable)) fmax(float, float); +FN_FUNC_FN_FN(fmax); +FN_FUNC_FN_F(fmax); + +extern float __attribute__((overloadable)) fmin(float, float); +FN_FUNC_FN_FN(fmin); +FN_FUNC_FN_F(fmin); + +extern float __attribute__((overloadable)) fmod(float, float); +FN_FUNC_FN_FN(fmod) + + +_RS_RUNTIME float __attribute__((overloadable)) fract(float v, float *iptr); +FN_FUNC_FN_PFN(fract) + +extern float __attribute__((overloadable)) frexp(float, int *); +FN_FUNC_FN_PIN(frexp) + +extern float __attribute__((overloadable)) hypot(float, float); +FN_FUNC_FN_FN(hypot) + +extern int __attribute__((overloadable)) ilogb(float); +IN_FUNC_FN(ilogb) + +extern float __attribute__((overloadable)) ldexp(float, int); +FN_FUNC_FN_IN(ldexp) +FN_FUNC_FN_I(ldexp) + +extern float __attribute__((overloadable)) lgamma(float); +FN_FUNC_FN(lgamma) +extern float __attribute__((overloadable)) lgamma(float, int*); +FN_FUNC_FN_PIN(lgamma) + +extern float __attribute__((overloadable)) log(float); +FN_FUNC_FN(log) + + +extern float __attribute__((overloadable)) log10(float); +FN_FUNC_FN(log10) + + +_RS_RUNTIME float __attribute__((overloadable)) log2(float v); +FN_FUNC_FN(log2) + +extern float __attribute__((overloadable)) log1p(float); +FN_FUNC_FN(log1p) + +extern float __attribute__((overloadable)) logb(float); +FN_FUNC_FN(logb) + +extern float __attribute__((overloadable)) mad(float, float, float); +FN_FUNC_FN_FN_FN(mad) + +extern float __attribute__((overloadable)) modf(float, float *); +FN_FUNC_FN_PFN(modf); + +//extern float __attribute__((overloadable)) nan(uint); + +extern float __attribute__((overloadable)) nextafter(float, float); +FN_FUNC_FN_FN(nextafter) + +FN_FUNC_FN_FN(pow) + +_RS_RUNTIME float __attribute__((overloadable)) pown(float v, int p); +_RS_RUNTIME float2 __attribute__((overloadable)) pown(float2 v, int2 p); +_RS_RUNTIME float3 __attribute__((overloadable)) pown(float3 v, int3 p); +_RS_RUNTIME float4 __attribute__((overloadable)) pown(float4 v, int4 p); + +_RS_RUNTIME float __attribute__((overloadable)) powr(float v, float p); +_RS_RUNTIME float2 __attribute__((overloadable)) powr(float2 v, float2 p); +_RS_RUNTIME float3 __attribute__((overloadable)) powr(float3 v, float3 p); +_RS_RUNTIME float4 __attribute__((overloadable)) powr(float4 v, float4 p); + +extern float __attribute__((overloadable)) remainder(float, float); +FN_FUNC_FN_FN(remainder) + +extern float __attribute__((overloadable)) remquo(float, float, int *); +FN_FUNC_FN_FN_PIN(remquo) + +extern float __attribute__((overloadable)) rint(float); +FN_FUNC_FN(rint) + + +_RS_RUNTIME float __attribute__((overloadable)) rootn(float v, int r); +_RS_RUNTIME float2 __attribute__((overloadable)) rootn(float2 v, int2 r); +_RS_RUNTIME float3 __attribute__((overloadable)) rootn(float3 v, int3 r); +_RS_RUNTIME float4 __attribute__((overloadable)) rootn(float4 v, int4 r); + + +extern float __attribute__((overloadable)) round(float); +FN_FUNC_FN(round) + + +extern float __attribute__((overloadable)) sqrt(float); +_RS_RUNTIME float __attribute__((overloadable)) rsqrt(float v); +FN_FUNC_FN(rsqrt) + +extern float __attribute__((overloadable)) sin(float); +FN_FUNC_FN(sin) + +_RS_RUNTIME float __attribute__((overloadable)) sincos(float v, float *cosptr); +_RS_RUNTIME float2 __attribute__((overloadable)) sincos(float2 v, float2 *cosptr); +_RS_RUNTIME float3 __attribute__((overloadable)) sincos(float3 v, float3 *cosptr); +_RS_RUNTIME float4 __attribute__((overloadable)) sincos(float4 v, float4 *cosptr); + +extern float __attribute__((overloadable)) sinh(float); +FN_FUNC_FN(sinh) + +_RS_RUNTIME float __attribute__((overloadable)) sinpi(float v); +FN_FUNC_FN(sinpi) + +FN_FUNC_FN(sqrt) + +extern float __attribute__((overloadable)) tan(float); +FN_FUNC_FN(tan) + +extern float __attribute__((overloadable)) tanh(float); +FN_FUNC_FN(tanh) + +_RS_RUNTIME float __attribute__((overloadable)) tanpi(float v); +FN_FUNC_FN(tanpi) + + +extern float __attribute__((overloadable)) tgamma(float); +FN_FUNC_FN(tgamma) + +extern float __attribute__((overloadable)) trunc(float); +FN_FUNC_FN(trunc) + +// Int ops (partial), 6.11.3 + +#define XN_FUNC_YN(typeout, fnc, typein) \ +extern typeout __attribute__((overloadable)) fnc(typein); \ +_RS_RUNTIME typeout##2 __attribute__((overloadable)) fnc(typein##2 v); \ +_RS_RUNTIME typeout##3 __attribute__((overloadable)) fnc(typein##3 v); \ +_RS_RUNTIME typeout##4 __attribute__((overloadable)) fnc(typein##4 v); + +#define UIN_FUNC_IN(fnc) \ +XN_FUNC_YN(uchar, fnc, char) \ +XN_FUNC_YN(ushort, fnc, short) \ +XN_FUNC_YN(uint, fnc, int) + +#define IN_FUNC_IN(fnc) \ +XN_FUNC_YN(uchar, fnc, uchar) \ +XN_FUNC_YN(char, fnc, char) \ +XN_FUNC_YN(ushort, fnc, ushort) \ +XN_FUNC_YN(short, fnc, short) \ +XN_FUNC_YN(uint, fnc, uint) \ +XN_FUNC_YN(int, fnc, int) + + +#define XN_FUNC_XN_XN_BODY(type, fnc, body) \ +_RS_RUNTIME type __attribute__((overloadable)) \ + fnc(type v1, type v2); \ +_RS_RUNTIME type##2 __attribute__((overloadable)) \ + fnc(type##2 v1, type##2 v2); \ +_RS_RUNTIME type##3 __attribute__((overloadable)) \ + fnc(type##3 v1, type##3 v2); \ +_RS_RUNTIME type##4 __attribute__((overloadable)) \ + fnc(type##4 v1, type##4 v2); + +#define IN_FUNC_IN_IN_BODY(fnc, body) \ +XN_FUNC_XN_XN_BODY(uchar, fnc, body) \ +XN_FUNC_XN_XN_BODY(char, fnc, body) \ +XN_FUNC_XN_XN_BODY(ushort, fnc, body) \ +XN_FUNC_XN_XN_BODY(short, fnc, body) \ +XN_FUNC_XN_XN_BODY(uint, fnc, body) \ +XN_FUNC_XN_XN_BODY(int, fnc, body) \ +XN_FUNC_XN_XN_BODY(float, fnc, body) + +UIN_FUNC_IN(abs) +IN_FUNC_IN(clz) + +IN_FUNC_IN_IN_BODY(min, (v1 < v2 ? v1 : v2)) +FN_FUNC_FN_F(min) + +IN_FUNC_IN_IN_BODY(max, (v1 > v2 ? v1 : v2)) +FN_FUNC_FN_F(max) + +// 6.11.4 + +_RS_RUNTIME float __attribute__((overloadable)) clamp(float amount, float low, float high); +_RS_RUNTIME float2 __attribute__((overloadable)) clamp(float2 amount, float2 low, float2 high); +_RS_RUNTIME float3 __attribute__((overloadable)) clamp(float3 amount, float3 low, float3 high); +_RS_RUNTIME float4 __attribute__((overloadable)) clamp(float4 amount, float4 low, float4 high); +_RS_RUNTIME float2 __attribute__((overloadable)) clamp(float2 amount, float low, float high); +_RS_RUNTIME float3 __attribute__((overloadable)) clamp(float3 amount, float low, float high); +_RS_RUNTIME float4 __attribute__((overloadable)) clamp(float4 amount, float low, float high); + +_RS_RUNTIME float __attribute__((overloadable)) degrees(float radians); +FN_FUNC_FN(degrees) + +_RS_RUNTIME float __attribute__((overloadable)) mix(float start, float stop, float amount); +_RS_RUNTIME float2 __attribute__((overloadable)) mix(float2 start, float2 stop, float2 amount); +_RS_RUNTIME float3 __attribute__((overloadable)) mix(float3 start, float3 stop, float3 amount); +_RS_RUNTIME float4 __attribute__((overloadable)) mix(float4 start, float4 stop, float4 amount); +_RS_RUNTIME float2 __attribute__((overloadable)) mix(float2 start, float2 stop, float amount); +_RS_RUNTIME float3 __attribute__((overloadable)) mix(float3 start, float3 stop, float amount); +_RS_RUNTIME float4 __attribute__((overloadable)) mix(float4 start, float4 stop, float amount); + +_RS_RUNTIME float __attribute__((overloadable)) radians(float degrees); +FN_FUNC_FN(radians) + +_RS_RUNTIME float __attribute__((overloadable)) step(float edge, float v); +_RS_RUNTIME float2 __attribute__((overloadable)) step(float2 edge, float2 v); +_RS_RUNTIME float3 __attribute__((overloadable)) step(float3 edge, float3 v); +_RS_RUNTIME float4 __attribute__((overloadable)) step(float4 edge, float4 v); +_RS_RUNTIME float2 __attribute__((overloadable)) step(float2 edge, float v); +_RS_RUNTIME float3 __attribute__((overloadable)) step(float3 edge, float v); +_RS_RUNTIME float4 __attribute__((overloadable)) step(float4 edge, float v); + +extern float __attribute__((overloadable)) smoothstep(float, float, float); +extern float2 __attribute__((overloadable)) smoothstep(float2, float2, float2); +extern float3 __attribute__((overloadable)) smoothstep(float3, float3, float3); +extern float4 __attribute__((overloadable)) smoothstep(float4, float4, float4); +extern float2 __attribute__((overloadable)) smoothstep(float, float, float2); +extern float3 __attribute__((overloadable)) smoothstep(float, float, float3); +extern float4 __attribute__((overloadable)) smoothstep(float, float, float4); + +_RS_RUNTIME float __attribute__((overloadable)) sign(float v); +FN_FUNC_FN(sign) + +// 6.11.5 +_RS_RUNTIME float3 __attribute__((overloadable)) cross(float3 lhs, float3 rhs); + +_RS_RUNTIME float4 __attribute__((overloadable)) cross(float4 lhs, float4 rhs); + +_RS_RUNTIME float __attribute__((overloadable)) dot(float lhs, float rhs); +_RS_RUNTIME float __attribute__((overloadable)) dot(float2 lhs, float2 rhs); +_RS_RUNTIME float __attribute__((overloadable)) dot(float3 lhs, float3 rhs); +_RS_RUNTIME float __attribute__((overloadable)) dot(float4 lhs, float4 rhs); + +_RS_RUNTIME float __attribute__((overloadable)) length(float v); +_RS_RUNTIME float __attribute__((overloadable)) length(float2 v); +_RS_RUNTIME float __attribute__((overloadable)) length(float3 v); +_RS_RUNTIME float __attribute__((overloadable)) length(float4 v); + +_RS_RUNTIME float __attribute__((overloadable)) distance(float lhs, float rhs); +_RS_RUNTIME float __attribute__((overloadable)) distance(float2 lhs, float2 rhs); +_RS_RUNTIME float __attribute__((overloadable)) distance(float3 lhs, float3 rhs); +_RS_RUNTIME float __attribute__((overloadable)) distance(float4 lhs, float4 rhs); + +_RS_RUNTIME float __attribute__((overloadable)) normalize(float v); +_RS_RUNTIME float2 __attribute__((overloadable)) normalize(float2 v); +_RS_RUNTIME float3 __attribute__((overloadable)) normalize(float3 v); +_RS_RUNTIME float4 __attribute__((overloadable)) normalize(float4 v); + +#undef CVT_FUNC +#undef CVT_FUNC_2 +#undef FN_FUNC_FN +#undef IN_FUNC_FN +#undef FN_FUNC_FN_FN +#undef FN_FUNC_FN_F +#undef FN_FUNC_FN_IN +#undef FN_FUNC_FN_I +#undef FN_FUNC_FN_PFN +#undef FN_FUNC_FN_PIN +#undef FN_FUNC_FN_FN_FN +#undef FN_FUNC_FN_FN_PIN +#undef XN_FUNC_YN +#undef UIN_FUNC_IN +#undef IN_FUNC_IN +#undef XN_FUNC_XN_XN_BODY +#undef IN_FUNC_IN_IN_BODY +#undef _RS_RUNTIME + +#endif diff --git a/libs/rs/scriptc/rs_core.rsh b/libs/rs/scriptc/rs_core.rsh new file mode 100644 index 0000000..e32d435 --- /dev/null +++ b/libs/rs/scriptc/rs_core.rsh @@ -0,0 +1,176 @@ +#ifndef __RS_CORE_RSH__ +#define __RS_CORE_RSH__ + +#define _RS_RUNTIME extern + +// Debugging, print to the LOG a description string and a value. +extern void __attribute__((overloadable)) + rsDebug(const char *, float); +extern void __attribute__((overloadable)) + rsDebug(const char *, float, float); +extern void __attribute__((overloadable)) + rsDebug(const char *, float, float, float); +extern void __attribute__((overloadable)) + rsDebug(const char *, float, float, float, float); +extern void __attribute__((overloadable)) + rsDebug(const char *, double); +extern void __attribute__((overloadable)) + rsDebug(const char *, const rs_matrix4x4 *); +extern void __attribute__((overloadable)) + rsDebug(const char *, const rs_matrix3x3 *); +extern void __attribute__((overloadable)) + rsDebug(const char *, const rs_matrix2x2 *); +extern void __attribute__((overloadable)) + rsDebug(const char *, int); +extern void __attribute__((overloadable)) + rsDebug(const char *, uint); +extern void __attribute__((overloadable)) + rsDebug(const char *, long); +extern void __attribute__((overloadable)) + rsDebug(const char *, unsigned long); +extern void __attribute__((overloadable)) + rsDebug(const char *, long long); +extern void __attribute__((overloadable)) + rsDebug(const char *, unsigned long long); +extern void __attribute__((overloadable)) + rsDebug(const char *, const void *); +#define RS_DEBUG(a) rsDebug(#a, a) +#define RS_DEBUG_MARKER rsDebug(__FILE__, __LINE__) + +_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float2 v); +_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float3 v); +_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float4 v); + +_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b); + +_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b, float a); + +_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float3 color); + +_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float4 color); + +_RS_RUNTIME float4 rsUnpackColor8888(uchar4 c); + +//extern uchar4 __attribute__((overloadable)) rsPackColorTo565(float r, float g, float b); +//extern uchar4 __attribute__((overloadable)) rsPackColorTo565(float3); +//extern float4 rsUnpackColor565(uchar4); + + +///////////////////////////////////////////////////// +// Matrix ops +///////////////////////////////////////////////////// + +_RS_RUNTIME void __attribute__((overloadable)) +rsMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v); + +_RS_RUNTIME float __attribute__((overloadable)) +rsMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col); + +_RS_RUNTIME void __attribute__((overloadable)) +rsMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v); + +_RS_RUNTIME float __attribute__((overloadable)) +rsMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col); + +_RS_RUNTIME void __attribute__((overloadable)) +rsMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v); + +_RS_RUNTIME float __attribute__((overloadable)) +rsMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col); + +extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix4x4 *m); +extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix3x3 *m); +extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix2x2 *m); +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const float *v); +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix3x3 *m, const float *v); +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix2x2 *m, const float *v); +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix4x4 *v); +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix3x3 *v); +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix2x2 *v); +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix3x3 *m, const rs_matrix3x3 *v); +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix2x2 *m, const rs_matrix2x2 *v); + +extern void __attribute__((overloadable)) +rsMatrixLoadRotate(rs_matrix4x4 *m, float rot, float x, float y, float z); + +extern void __attribute__((overloadable)) +rsMatrixLoadScale(rs_matrix4x4 *m, float x, float y, float z); + +extern void __attribute__((overloadable)) +rsMatrixLoadTranslate(rs_matrix4x4 *m, float x, float y, float z); + +extern void __attribute__((overloadable)) +rsMatrixLoadMultiply(rs_matrix4x4 *m, const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs); + +extern void __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix4x4 *m, const rs_matrix4x4 *rhs); + +extern void __attribute__((overloadable)) +rsMatrixLoadMultiply(rs_matrix3x3 *m, const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs); + +extern void __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix3x3 *m, const rs_matrix3x3 *rhs); + +extern void __attribute__((overloadable)) +rsMatrixLoadMultiply(rs_matrix2x2 *m, const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs); + +extern void __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix2x2 *m, const rs_matrix2x2 *rhs); + +extern void __attribute__((overloadable)) +rsMatrixRotate(rs_matrix4x4 *m, float rot, float x, float y, float z); + +extern void __attribute__((overloadable)) +rsMatrixScale(rs_matrix4x4 *m, float x, float y, float z); + +extern void __attribute__((overloadable)) +rsMatrixTranslate(rs_matrix4x4 *m, float x, float y, float z); + +extern void __attribute__((overloadable)) +rsMatrixLoadOrtho(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far); + +extern void __attribute__((overloadable)) +rsMatrixLoadFrustum(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far); + +extern void __attribute__((overloadable)) +rsMatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far); + +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix4x4 *m, float4 in); + +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix4x4 *m, float3 in); + +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix4x4 *m, float2 in); + +_RS_RUNTIME float3 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix3x3 *m, float3 in); + +_RS_RUNTIME float3 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix3x3 *m, float2 in); + +_RS_RUNTIME float2 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix2x2 *m, float2 in); + +// Returns true if the matrix was successfully inversed +extern bool __attribute__((overloadable)) rsMatrixInverse(rs_matrix4x4 *m); +extern bool __attribute__((overloadable)) rsMatrixInverseTranspose(rs_matrix4x4 *m); +extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix4x4 *m); +extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix3x3 *m); +extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix2x2 *m); + +///////////////////////////////////////////////////// +// int ops +///////////////////////////////////////////////////// + +_RS_RUNTIME uint __attribute__((overloadable, always_inline)) rsClamp(uint amount, uint low, uint high); +_RS_RUNTIME int __attribute__((overloadable, always_inline)) rsClamp(int amount, int low, int high); +_RS_RUNTIME ushort __attribute__((overloadable, always_inline)) rsClamp(ushort amount, ushort low, ushort high); +_RS_RUNTIME short __attribute__((overloadable, always_inline)) rsClamp(short amount, short low, short high); +_RS_RUNTIME uchar __attribute__((overloadable, always_inline)) rsClamp(uchar amount, uchar low, uchar high); +_RS_RUNTIME char __attribute__((overloadable, always_inline)) rsClamp(char amount, char low, char high); + +#undef _RS_RUNTIME + +#endif diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh index 70cd562..3868f24 100644 --- a/libs/rs/scriptc/rs_graphics.rsh +++ b/libs/rs/scriptc/rs_graphics.rsh @@ -1,65 +1,105 @@ - - -extern float2 vec2Rand(float len); - -extern float3 float3Norm(float3); -extern float float3Length(float3); -extern float3 float3Add(float3 lhs, float3 rhs); -extern float3 float3Sub(float3 lhs, float3 rhs); -extern float3 float3Cross(float3 lhs, float3 rhs); -extern float float3Dot(float3 lhs, float3 rhs); -extern float3 float3Scale(float3 v, float scale); - -extern float4 float4Add(float4 lhs, float4 rhs); -extern float4 float4Sub(float4 lhs, float4 rhs); -extern float4 float4Cross(float4 lhs, float4 rhs); -extern float float4Dot(float4 lhs, float4 rhs); -extern float4 float4Scale(float4 v, float scale); - - // context -extern void bindProgramFragment(rs_program_fragment); -extern void bindProgramStore(rs_program_store); -extern void bindProgramVertex(rs_program_vertex); - -extern void bindSampler(rs_program_fragment, int slot, rs_sampler); -extern void bindSampler(rs_program_fragment, int slot, rs_allocation); - -extern void vpLoadModelMatrix(const float *); -extern void vpLoadTextureMatrix(const float *); - - -// drawing -extern void drawRect(float x1, float y1, float x2, float y2, float z); -extern void 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); -extern void 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); -extern void drawSprite(float x, float y, float z, float w, float h); -extern void drawSpriteScreenspace(float x, float y, float z, float w, float h); -extern void drawLine(float x1, float y1, float z1, float x2, float y2, float z2); -extern void drawPoint(float x1, float y1, float z1); -extern void drawSimpleMesh(int ism); -extern void drawSimpleMeshRange(int ism, int start, int len); - +#ifndef __RS_GRAPHICS_RSH__ +#define __RS_GRAPHICS_RSH__ + +// Bind a ProgramFragment to the RS context. +extern void __attribute__((overloadable)) + rsgBindProgramFragment(rs_program_fragment); +extern void __attribute__((overloadable)) + rsgBindProgramStore(rs_program_store); +extern void __attribute__((overloadable)) + rsgBindProgramVertex(rs_program_vertex); +extern void __attribute__((overloadable)) + rsgBindProgramRaster(rs_program_raster); + +extern void __attribute__((overloadable)) + rsgBindSampler(rs_program_fragment, uint slot, rs_sampler); +extern void __attribute__((overloadable)) + rsgBindTexture(rs_program_fragment, uint slot, rs_allocation); + +extern void __attribute__((overloadable)) + rsgProgramVertexLoadProjectionMatrix(const rs_matrix4x4 *); +extern void __attribute__((overloadable)) + rsgProgramVertexLoadModelMatrix(const rs_matrix4x4 *); +extern void __attribute__((overloadable)) + rsgProgramVertexLoadTextureMatrix(const rs_matrix4x4 *); + +extern void __attribute__((overloadable)) + rsgProgramVertexGetProjectionMatrix(rs_matrix4x4 *); + +extern void __attribute__((overloadable)) + rsgProgramFragmentConstantColor(rs_program_fragment, float, float, float, float); + +extern uint __attribute__((overloadable)) + rsgGetWidth(void); +extern uint __attribute__((overloadable)) + rsgGetHeight(void); + +extern void __attribute__((overloadable)) + rsgAllocationSyncAll(rs_allocation); + +extern void __attribute__((overloadable)) + rsgDrawRect(float x1, float y1, float x2, float y2, float z); +extern void __attribute__((overloadable)) + rsgDrawQuad(float x1, float y1, float z1, + float x2, float y2, float z2, + float x3, float y3, float z3, + float x4, float y4, float z4); +extern void __attribute__((overloadable)) + rsgDrawQuadTexCoords(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); +extern void __attribute__((overloadable)) + rsgDrawSpriteScreenspace(float x, float y, float z, float w, float h); + +extern void __attribute__((overloadable)) + rsgDrawMesh(rs_mesh ism); +extern void __attribute__((overloadable)) + rsgDrawMesh(rs_mesh ism, uint primitiveIndex); +extern void __attribute__((overloadable)) + rsgDrawMesh(rs_mesh ism, uint primitiveIndex, uint start, uint len); + +extern void __attribute__((overloadable)) + rsgClearColor(float, float, float, float); +extern void __attribute__((overloadable)) + rsgClearDepth(float); + +extern void __attribute__((overloadable)) + rsgDrawText(const char *, int x, int y); +extern void __attribute__((overloadable)) + rsgDrawText(rs_allocation, int x, int y); +extern void __attribute__((overloadable)) + rsgBindFont(rs_font); +extern void __attribute__((overloadable)) + rsgFontColor(float, float, float, float); +// Returns the bounding box of the text relative to (0, 0) +// Any of left, right, top, bottom could be NULL +extern void __attribute__((overloadable)) + rsgMeasureText(const char *, int *left, int *right, int *top, int *bottom); +extern void __attribute__((overloadable)) + rsgMeasureText(rs_allocation, int *left, int *right, int *top, int *bottom); + +extern void __attribute__((overloadable)) + rsgMeshComputeBoundingBox(rs_mesh mesh, float *minX, float *minY, float *minZ, + float *maxX, float *maxY, float *maxZ); +__inline__ static void __attribute__((overloadable, always_inline)) +rsgMeshComputeBoundingBox(rs_mesh mesh, float3 *bBoxMin, float3 *bBoxMax) { + float x1, y1, z1, x2, y2, z2; + rsgMeshComputeBoundingBox(mesh, &x1, &y1, &z1, &x2, &y2, &z2); + bBoxMin->x = x1; + bBoxMin->y = y1; + bBoxMin->z = z1; + bBoxMax->x = x2; + bBoxMax->y = y2; + bBoxMax->z = z2; +} + +/////////////////////////////////////////////////////// // misc -extern void pfClearColor(float, float, float, float); -extern void color(float, float, float, float); -extern void hsb(float, float, float, float); -extern void hsbToRgb(float, float, float, float*); -extern int hsbToAbgr(float, float, float, float); - -extern void uploadToTexture(int, int); -extern void uploadToBufferObject(int); - -extern int colorFloatRGBAtoUNorm8(float, float, float, float); -extern int colorFloatRGBto565(float, float, float); - -extern int getWidth(); -extern int getHeight(); - -extern int sendToClient(void *data, int cmdID, int len, int waitForSpace); - -extern void debugF(const char *, float); -extern void debugI32(const char *, int); -extern void debugHexI32(const char *, int); +// Depricated +extern void __attribute__((overloadable)) + color(float, float, float, float); +#endif diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh index 613c7ca..a74c0e0 100644 --- a/libs/rs/scriptc/rs_math.rsh +++ b/libs/rs/scriptc/rs_math.rsh @@ -1,287 +1,168 @@ -// Float ops - -extern float __attribute__((overloadable)) abs(float); -extern float2 __attribute__((overloadable)) abs(float2); -extern float3 __attribute__((overloadable)) abs(float3); -extern float4 __attribute__((overloadable)) abs(float4); -extern float8 __attribute__((overloadable)) abs(float8); -extern float16 __attribute__((overloadable)) abs(float16); - -extern float __attribute__((overloadable)) acos(float); -extern float2 __attribute__((overloadable)) acos(float2); -extern float3 __attribute__((overloadable)) acos(float3); -extern float4 __attribute__((overloadable)) acos(float4); -extern float8 __attribute__((overloadable)) acos(float8); -extern float16 __attribute__((overloadable)) acos(float16); - -extern float __attribute__((overloadable)) asin(float); -extern float2 __attribute__((overloadable)) asin(float2); -extern float3 __attribute__((overloadable)) asin(float3); -extern float4 __attribute__((overloadable)) asin(float4); -extern float8 __attribute__((overloadable)) asin(float8); -extern float16 __attribute__((overloadable)) asin(float16); - -extern float __attribute__((overloadable)) atan(float); -extern float2 __attribute__((overloadable)) atan(float2); -extern float3 __attribute__((overloadable)) atan(float3); -extern float4 __attribute__((overloadable)) atan(float4); -extern float8 __attribute__((overloadable)) atan(float8); -extern float16 __attribute__((overloadable)) atan(float16); - -extern float __attribute__((overloadable)) atan2(float, float); -extern float2 __attribute__((overloadable)) atan2(float2, float2); -extern float3 __attribute__((overloadable)) atan2(float3, float3); -extern float4 __attribute__((overloadable)) atan2(float4, float4); -extern float8 __attribute__((overloadable)) atan2(float8, float8); -extern float16 __attribute__((overloadable)) atan2(float16, float16); - -extern float __attribute__((overloadable)) ceil(float); -extern float2 __attribute__((overloadable)) ceil(float2); -extern float3 __attribute__((overloadable)) ceil(float3); -extern float4 __attribute__((overloadable)) ceil(float4); -extern float8 __attribute__((overloadable)) ceil(float8); -extern float16 __attribute__((overloadable)) ceil(float16); - -extern float __attribute__((overloadable)) clamp(float, float, float); -extern float2 __attribute__((overloadable)) clamp(float2, float2, float2); -extern float3 __attribute__((overloadable)) clamp(float3, float3, float3); -extern float4 __attribute__((overloadable)) clamp(float4, float4, float4); -extern float8 __attribute__((overloadable)) clamp(float8, float8, float8); -extern float16 __attribute__((overloadable)) clamp(float16, float16, float16); -extern float __attribute__((overloadable)) clamp(float, float, float); -extern float2 __attribute__((overloadable)) clamp(float2, float, float); -extern float3 __attribute__((overloadable)) clamp(float3, float, float); -extern float4 __attribute__((overloadable)) clamp(float4, float, float); -extern float8 __attribute__((overloadable)) clamp(float8, float, float); -extern float16 __attribute__((overloadable)) clamp(float16, float, float); - -extern float __attribute__((overloadable)) copysign(float, float); -extern float2 __attribute__((overloadable)) copysign(float2, float2); -extern float3 __attribute__((overloadable)) copysign(float3, float3); -extern float4 __attribute__((overloadable)) copysign(float4, float4); -extern float8 __attribute__((overloadable)) copysign(float8, float8); -extern float16 __attribute__((overloadable)) copysign(float16, float16); - -extern float __attribute__((overloadable)) cos(float); -extern float2 __attribute__((overloadable)) cos(float2); -extern float3 __attribute__((overloadable)) cos(float3); -extern float4 __attribute__((overloadable)) cos(float4); -extern float8 __attribute__((overloadable)) cos(float8); -extern float16 __attribute__((overloadable)) cos(float16); - -extern float __attribute__((overloadable)) degrees(float); -extern float2 __attribute__((overloadable)) degrees(float2); -extern float3 __attribute__((overloadable)) degrees(float3); -extern float4 __attribute__((overloadable)) degrees(float4); -extern float8 __attribute__((overloadable)) degrees(float8); -extern float16 __attribute__((overloadable)) degrees(float16); - -extern float __attribute__((overloadable)) exp(float); -extern float2 __attribute__((overloadable)) exp(float2); -extern float3 __attribute__((overloadable)) exp(float3); -extern float4 __attribute__((overloadable)) exp(float4); -extern float8 __attribute__((overloadable)) exp(float8); -extern float16 __attribute__((overloadable)) exp(float16); - -extern float __attribute__((overloadable)) exp2(float); -extern float2 __attribute__((overloadable)) exp2(float2); -extern float3 __attribute__((overloadable)) exp2(float3); -extern float4 __attribute__((overloadable)) exp2(float4); -extern float8 __attribute__((overloadable)) exp2(float8); -extern float16 __attribute__((overloadable)) exp2(float16); - -extern float __attribute__((overloadable)) exp10(float); -extern float2 __attribute__((overloadable)) exp10(float2); -extern float3 __attribute__((overloadable)) exp10(float3); -extern float4 __attribute__((overloadable)) exp10(float4); -extern float8 __attribute__((overloadable)) exp10(float8); -extern float16 __attribute__((overloadable)) exp10(float16); - -extern float __attribute__((overloadable)) fabs(float); -extern float2 __attribute__((overloadable)) fabs(float2); -extern float3 __attribute__((overloadable)) fabs(float3); -extern float4 __attribute__((overloadable)) fabs(float4); -extern float8 __attribute__((overloadable)) fabs(float8); -extern float16 __attribute__((overloadable)) fabs(float16); - -extern float __attribute__((overloadable)) floor(float); -extern float2 __attribute__((overloadable)) floor(float2); -extern float3 __attribute__((overloadable)) floor(float3); -extern float4 __attribute__((overloadable)) floor(float4); -extern float8 __attribute__((overloadable)) floor(float8); -extern float16 __attribute__((overloadable)) floor(float16); - -extern float __attribute__((overloadable)) fmax(float, float); -extern float2 __attribute__((overloadable)) fmax(float2, float2); -extern float3 __attribute__((overloadable)) fmax(float3, float3); -extern float4 __attribute__((overloadable)) fmax(float4, float4); -extern float8 __attribute__((overloadable)) fmax(float8, float8); -extern float16 __attribute__((overloadable)) fmax(float16, float16); -extern float2 __attribute__((overloadable)) fmax(float2, float); -extern float3 __attribute__((overloadable)) fmax(float3, float); -extern float4 __attribute__((overloadable)) fmax(float4, float); -extern float8 __attribute__((overloadable)) fmax(float8, float); -extern float16 __attribute__((overloadable)) fmax(float16, float); - -extern float __attribute__((overloadable)) fmin(float, float); -extern float2 __attribute__((overloadable)) fmin(float2, float2); -extern float3 __attribute__((overloadable)) fmin(float3, float3); -extern float4 __attribute__((overloadable)) fmin(float4, float4); -extern float8 __attribute__((overloadable)) fmin(float8, float8); -extern float16 __attribute__((overloadable)) fmin(float16, float16); -extern float2 __attribute__((overloadable)) fmin(float2, float); -extern float3 __attribute__((overloadable)) fmin(float3, float); -extern float4 __attribute__((overloadable)) fmin(float4, float); -extern float8 __attribute__((overloadable)) fmin(float8, float); -extern float16 __attribute__((overloadable)) fmin(float16, float); - -extern float __attribute__((overloadable)) fmod(float, float); -extern float2 __attribute__((overloadable)) fmod(float2, float2); -extern float3 __attribute__((overloadable)) fmod(float3, float3); -extern float4 __attribute__((overloadable)) fmod(float4, float4); -extern float8 __attribute__((overloadable)) fmod(float8, float8); -extern float16 __attribute__((overloadable)) fmod(float16, float16); - -extern float __attribute__((overloadable)) log(float); -extern float2 __attribute__((overloadable)) log(float2); -extern float3 __attribute__((overloadable)) log(float3); -extern float4 __attribute__((overloadable)) log(float4); -extern float8 __attribute__((overloadable)) log(float8); -extern float16 __attribute__((overloadable)) log(float16); - -extern float __attribute__((overloadable)) log2(float); -extern float2 __attribute__((overloadable)) log2(float2); -extern float3 __attribute__((overloadable)) log2(float3); -extern float4 __attribute__((overloadable)) log2(float4); -extern float8 __attribute__((overloadable)) log2(float8); -extern float16 __attribute__((overloadable)) log2(float16); - -extern float __attribute__((overloadable)) log10(float); -extern float2 __attribute__((overloadable)) log10(float2); -extern float3 __attribute__((overloadable)) log10(float3); -extern float4 __attribute__((overloadable)) log10(float4); -extern float8 __attribute__((overloadable)) log10(float8); -extern float16 __attribute__((overloadable)) log10(float16); - -extern float __attribute__((overloadable)) max(float, float); -extern float2 __attribute__((overloadable)) max(float2, float2); -extern float3 __attribute__((overloadable)) max(float3, float3); -extern float4 __attribute__((overloadable)) max(float4, float4); -extern float8 __attribute__((overloadable)) max(float8, float8); -extern float16 __attribute__((overloadable)) max(float16, float16); - -extern float __attribute__((overloadable)) min(float, float); -extern float2 __attribute__((overloadable)) min(float2, float2); -extern float3 __attribute__((overloadable)) min(float3, float3); -extern float4 __attribute__((overloadable)) min(float4, float4); -extern float8 __attribute__((overloadable)) min(float8, float8); -extern float16 __attribute__((overloadable)) min(float16, float16); - -extern float __attribute__((overloadable)) mix(float, float, float); -extern float2 __attribute__((overloadable)) mix(float2, float2, float2); -extern float3 __attribute__((overloadable)) mix(float3, float3, float3); -extern float4 __attribute__((overloadable)) mix(float4, float4, float4); -extern float8 __attribute__((overloadable)) mix(float8, float8, float8); -extern float16 __attribute__((overloadable)) mix(float16, float16, float16); -extern float __attribute__((overloadable)) mix(float, float, float); -extern float2 __attribute__((overloadable)) mix(float2, float2, float); -extern float3 __attribute__((overloadable)) mix(float3, float3, float); -extern float4 __attribute__((overloadable)) mix(float4, float4, float); -extern float8 __attribute__((overloadable)) mix(float8, float8, float); -extern float16 __attribute__((overloadable)) mix(float16, float16, float); - -extern float __attribute__((overloadable)) pow(float, float); -extern float2 __attribute__((overloadable)) pow(float2, float2); -extern float3 __attribute__((overloadable)) pow(float3, float3); -extern float4 __attribute__((overloadable)) pow(float4, float4); -extern float8 __attribute__((overloadable)) pow(float8, float8); -extern float16 __attribute__((overloadable)) pow(float16, float16); - -extern float __attribute__((overloadable)) radians(float); -extern float2 __attribute__((overloadable)) radians(float2); -extern float3 __attribute__((overloadable)) radians(float3); -extern float4 __attribute__((overloadable)) radians(float4); -extern float8 __attribute__((overloadable)) radians(float8); -extern float16 __attribute__((overloadable)) radians(float16); - -extern float __attribute__((overloadable)) rint(float); -extern float2 __attribute__((overloadable)) rint(float2); -extern float3 __attribute__((overloadable)) rint(float3); -extern float4 __attribute__((overloadable)) rint(float4); -extern float8 __attribute__((overloadable)) rint(float8); -extern float16 __attribute__((overloadable)) rint(float16); - -extern float __attribute__((overloadable)) round(float); -extern float2 __attribute__((overloadable)) round(float2); -extern float3 __attribute__((overloadable)) round(float3); -extern float4 __attribute__((overloadable)) round(float4); -extern float8 __attribute__((overloadable)) round(float8); -extern float16 __attribute__((overloadable)) round(float16); - -extern float __attribute__((overloadable)) rsqrt(float); -extern float2 __attribute__((overloadable)) rsqrt(float2); -extern float3 __attribute__((overloadable)) rsqrt(float3); -extern float4 __attribute__((overloadable)) rsqrt(float4); -extern float8 __attribute__((overloadable)) rsqrt(float8); -extern float16 __attribute__((overloadable)) rsqrt(float16); - -extern float __attribute__((overloadable)) sign(float); -extern float2 __attribute__((overloadable)) sign(float2); -extern float3 __attribute__((overloadable)) sign(float3); -extern float4 __attribute__((overloadable)) sign(float4); -extern float8 __attribute__((overloadable)) sign(float8); -extern float16 __attribute__((overloadable)) sign(float16); - -extern float __attribute__((overloadable)) sin(float); -extern float2 __attribute__((overloadable)) sin(float2); -extern float3 __attribute__((overloadable)) sin(float3); -extern float4 __attribute__((overloadable)) sin(float4); -extern float8 __attribute__((overloadable)) sin(float8); -extern float16 __attribute__((overloadable)) sin(float16); - -extern float __attribute__((overloadable)) sqrt(float); -extern float2 __attribute__((overloadable)) sqrt(float2); -extern float3 __attribute__((overloadable)) sqrt(float3); -extern float4 __attribute__((overloadable)) sqrt(float4); -extern float8 __attribute__((overloadable)) sqrt(float8); -extern float16 __attribute__((overloadable)) sqrt(float16); - -extern float __attribute__((overloadable)) tan(float); -extern float2 __attribute__((overloadable)) tan(float2); -extern float3 __attribute__((overloadable)) tan(float3); -extern float4 __attribute__((overloadable)) tan(float4); -extern float8 __attribute__((overloadable)) tan(float8); -extern float16 __attribute__((overloadable)) tan(float16); - -extern float __attribute__((overloadable)) trunc(float); -extern float2 __attribute__((overloadable)) trunc(float2); -extern float3 __attribute__((overloadable)) trunc(float3); -extern float4 __attribute__((overloadable)) trunc(float4); -extern float8 __attribute__((overloadable)) trunc(float8); -extern float16 __attribute__((overloadable)) trunc(float16); - - - - - - -// Int ops - -extern int __attribute__((overloadable)) abs(int); -extern int2 __attribute__((overloadable)) abs(int2); -extern int3 __attribute__((overloadable)) abs(int3); -extern int4 __attribute__((overloadable)) abs(int4); -extern int8 __attribute__((overloadable)) abs(int8); -extern int16 __attribute__((overloadable)) abs(int16); - - - -/* -extern float modf(float, float); -extern float randf(float); -extern float randf2(float, float); -extern float fracf(float); -extern float lerpf(float, float, float); -extern float mapf(float, float, float, float, float); -*/ - +#ifndef __RS_MATH_RSH__ +#define __RS_MATH_RSH__ + +extern void __attribute__((overloadable)) + rsSetObject(rs_element *dst, rs_element src); +extern void __attribute__((overloadable)) + rsSetObject(rs_type *dst, rs_type src); +extern void __attribute__((overloadable)) + rsSetObject(rs_allocation *dst, rs_allocation src); +extern void __attribute__((overloadable)) + rsSetObject(rs_sampler *dst, rs_sampler src); +extern void __attribute__((overloadable)) + rsSetObject(rs_script *dst, rs_script src); +extern void __attribute__((overloadable)) + rsSetObject(rs_mesh *dst, rs_mesh src); +extern void __attribute__((overloadable)) + rsSetObject(rs_program_fragment *dst, rs_program_fragment src); +extern void __attribute__((overloadable)) + rsSetObject(rs_program_vertex *dst, rs_program_vertex src); +extern void __attribute__((overloadable)) + rsSetObject(rs_program_raster *dst, rs_program_raster src); +extern void __attribute__((overloadable)) + rsSetObject(rs_program_store *dst, rs_program_store src); +extern void __attribute__((overloadable)) + rsSetObject(rs_font *dst, rs_font src); + +extern void __attribute__((overloadable)) + rsClearObject(rs_element *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_type *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_allocation *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_sampler *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_script *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_mesh *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_program_fragment *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_program_vertex *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_program_raster *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_program_store *dst); +extern void __attribute__((overloadable)) + rsClearObject(rs_font *dst); + +extern bool __attribute__((overloadable)) + rsIsObject(rs_element); +extern bool __attribute__((overloadable)) + rsIsObject(rs_type); +extern bool __attribute__((overloadable)) + rsIsObject(rs_allocation); +extern bool __attribute__((overloadable)) + rsIsObject(rs_sampler); +extern bool __attribute__((overloadable)) + rsIsObject(rs_script); +extern bool __attribute__((overloadable)) + rsIsObject(rs_mesh); +extern bool __attribute__((overloadable)) + rsIsObject(rs_program_fragment); +extern bool __attribute__((overloadable)) + rsIsObject(rs_program_vertex); +extern bool __attribute__((overloadable)) + rsIsObject(rs_program_raster); +extern bool __attribute__((overloadable)) + rsIsObject(rs_program_store); +extern bool __attribute__((overloadable)) + rsIsObject(rs_font); + + + +// Allocations + +// Return the rs_allocation associated with a bound data +// pointer. +extern rs_allocation __attribute__((overloadable)) + rsGetAllocation(const void *); + +// Mark the allocation dirty and notify those using it +extern void __attribute__((overloadable)) + rsAllocationMarkDirty(rs_allocation); + +// Return the dimensions associated with an allocation. +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimX(rs_allocation); +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimY(rs_allocation); +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimZ(rs_allocation); +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimLOD(rs_allocation); +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimFaces(rs_allocation); + +// Extract a single element from an allocation. +extern const void * __attribute__((overloadable)) + rsGetElementAt(rs_allocation, uint32_t x); +extern const void * __attribute__((overloadable)) + rsGetElementAt(rs_allocation, uint32_t x, uint32_t y); +extern const void * __attribute__((overloadable)) + rsGetElementAt(rs_allocation, uint32_t x, uint32_t y, uint32_t z); + +// Return a random value between 0 (or min_value) and max_malue. +extern int __attribute__((overloadable)) + rsRand(int max_value); +extern int __attribute__((overloadable)) + rsRand(int min_value, int max_value); +extern float __attribute__((overloadable)) + rsRand(float max_value); +extern float __attribute__((overloadable)) + rsRand(float min_value, float max_value); + +// return the fractional part of a float +// min(v - ((int)floor(v)), 0x1.fffffep-1f); +extern float __attribute__((overloadable)) + rsFrac(float); + +// Send a message back to the client. Will not block and returns true +// if the message was sendable and false if the fifo was full. +// A message ID is required. Data payload is optional. +extern bool __attribute__((overloadable)) + rsSendToClient(int cmdID); +extern bool __attribute__((overloadable)) + rsSendToClient(int cmdID, const void *data, uint len); + +// Send a message back to the client, blocking until the message is queued. +// A message ID is required. Data payload is optional. +extern void __attribute__((overloadable)) + rsSendToClientBlocking(int cmdID); +extern void __attribute__((overloadable)) + rsSendToClientBlocking(int cmdID, const void *data, uint len); + + +// Script to Script +enum rs_for_each_strategy { + RS_FOR_EACH_STRATEGY_SERIAL, + RS_FOR_EACH_STRATEGY_DONT_CARE, + RS_FOR_EACH_STRATEGY_DST_LINEAR, + RS_FOR_EACH_STRATEGY_TILE_SMALL, + RS_FOR_EACH_STRATEGY_TILE_MEDIUM, + RS_FOR_EACH_STRATEGY_TILE_LARGE +}; + +typedef struct rs_script_call { + enum rs_for_each_strategy strategy; + uint32_t xStart; + uint32_t xEnd; + uint32_t yStart; + uint32_t yEnd; + uint32_t zStart; + uint32_t zEnd; + uint32_t arrayStart; + uint32_t arrayEnd; +} rs_script_call_t; + +extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, + rs_allocation output, const void * usrData); + +extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, + rs_allocation output, const void * usrData, + const rs_script_call_t *); + +#endif diff --git a/libs/rs/scriptc/rs_time.rsh b/libs/rs/scriptc/rs_time.rsh new file mode 100644 index 0000000..f1abed6 --- /dev/null +++ b/libs/rs/scriptc/rs_time.rsh @@ -0,0 +1,36 @@ +#ifndef __RS_TIME_RSH__ +#define __RS_TIME_RSH__ + +typedef int rs_time_t; + +typedef struct { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +} rs_tm; + +extern rs_time_t __attribute__((overloadable)) + rsTime(rs_time_t *timer); + +extern rs_tm * __attribute__((overloadable)) + rsLocaltime(rs_tm *local, const rs_time_t *timer); + +// Return the current system clock in milliseconds +extern int64_t __attribute__((overloadable)) + rsUptimeMillis(void); + +// Return the current system clock in nanoseconds +extern int64_t __attribute__((overloadable)) + rsUptimeNanos(void); + +// Return the time in seconds since function was last called in this script. +extern float __attribute__((overloadable)) + rsGetDt(void); + +#endif diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh index 4198a74..a010096 100644 --- a/libs/rs/scriptc/rs_types.rsh +++ b/libs/rs/scriptc/rs_types.rsh @@ -1,71 +1,80 @@ +#ifndef __RS_TYPES_RSH__ +#define __RS_TYPES_RSH__ +#define M_PI 3.14159265358979323846264338327950288f /* pi */ + +#include "stdbool.h" typedef char int8_t; typedef short int16_t; typedef int int32_t; -//typedef long int64_t; +typedef long long int64_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; -//typedef long uint64_t; +typedef unsigned long long uint64_t; typedef uint8_t uchar; typedef uint16_t ushort; typedef uint32_t uint; -//typedef uint64_t ulong; - -typedef int rs_element; -typedef int rs_type; -typedef int rs_allocation; -typedef int rs_sampler; -typedef int rs_script; -typedef int rs_mesh; -typedef int rs_program_fragment; -typedef int rs_program_vertex; -typedef int rs_program_raster; -typedef int rs_program_store; +typedef uint64_t ulong; + +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_element; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_type; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_allocation; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_sampler; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_script; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_mesh; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_fragment; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_vertex; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_raster; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_store; +typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_font; + 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 float float8 __attribute__((ext_vector_type(8))); -typedef float float16 __attribute__((ext_vector_type(16))); typedef uchar uchar2 __attribute__((ext_vector_type(2))); typedef uchar uchar3 __attribute__((ext_vector_type(3))); typedef uchar uchar4 __attribute__((ext_vector_type(4))); -typedef uchar uchar8 __attribute__((ext_vector_type(8))); -typedef uchar uchar16 __attribute__((ext_vector_type(16))); typedef ushort ushort2 __attribute__((ext_vector_type(2))); typedef ushort ushort3 __attribute__((ext_vector_type(3))); typedef ushort ushort4 __attribute__((ext_vector_type(4))); -typedef ushort ushort8 __attribute__((ext_vector_type(8))); -typedef ushort ushort16 __attribute__((ext_vector_type(16))); 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 uint uint8 __attribute__((ext_vector_type(8))); -typedef uint uint16 __attribute__((ext_vector_type(16))); typedef char char2 __attribute__((ext_vector_type(2))); typedef char char3 __attribute__((ext_vector_type(3))); typedef char char4 __attribute__((ext_vector_type(4))); -typedef char char8 __attribute__((ext_vector_type(8))); -typedef char char16 __attribute__((ext_vector_type(16))); typedef short short2 __attribute__((ext_vector_type(2))); typedef short short3 __attribute__((ext_vector_type(3))); typedef short short4 __attribute__((ext_vector_type(4))); -typedef short short8 __attribute__((ext_vector_type(8))); -typedef short short16 __attribute__((ext_vector_type(16))); 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 int int8 __attribute__((ext_vector_type(8))); -typedef int int16 __attribute__((ext_vector_type(16))); +typedef struct { + float m[16]; +} rs_matrix4x4; + +typedef struct { + float m[9]; +} rs_matrix3x3; + +typedef struct { + float m[4]; +} rs_matrix2x2; + +typedef float4 rs_quaternion; + +#define RS_PACKED __attribute__((packed, aligned(4))) +#endif |
