| // Copyright (C) 2012 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.scenegraph) |
| |
| #include "scenegraph_objects.rsh" |
| |
| //#define DEBUG_PARAMS |
| static inline void debugParam(SgShaderParam *p, SgShaderParamData *pData) { |
| rsDebug("____________ Param ____________", p); |
| printName(pData->paramName); |
| rsDebug("bufferOffset", p->bufferOffset); |
| rsDebug("type ", pData->type); |
| rsDebug("data timestamp ", pData->timestamp); |
| rsDebug("param timestamp", p->dataTimestamp); |
| |
| const SgTransform *pTransform = NULL; |
| if (rsIsObject(pData->transform)) { |
| pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0); |
| |
| rsDebug("transform", pTransform); |
| printName(pTransform->name); |
| rsDebug("timestamp", pTransform->timestamp); |
| rsDebug("param timestamp", p->transformTimestamp); |
| } |
| |
| const SgLight *pLight = NULL; |
| if (rsIsObject(pData->light)) { |
| pLight = (const SgLight *)rsGetElementAt(pData->light, 0); |
| printLightInfo(pLight); |
| } |
| } |
| |
| static inline void writeFloatData(float *ptr, const float4 *input, uint32_t vecSize) { |
| #ifdef DEBUG_PARAMS |
| rsDebug("Writing value ", *input); |
| rsDebug("Writing vec size ", vecSize); |
| #endif // DEBUG_PARAMS |
| |
| switch (vecSize) { |
| case 1: |
| *ptr = input->x; |
| break; |
| case 2: |
| *((float2*)ptr) = (*input).xy; |
| break; |
| case 3: |
| *((float3*)ptr) = (*input).xyz; |
| break; |
| case 4: |
| *((float4*)ptr) = *input; |
| break; |
| } |
| } |
| |
| static inline bool processParam(SgShaderParam *p, SgShaderParamData *pData, |
| uint8_t *constantBuffer, |
| const SgCamera *currentCam, |
| SgFragmentShader *shader) { |
| bool isDataOnly = (pData->type > SHADER_PARAM_DATA_ONLY); |
| const SgTransform *pTransform = NULL; |
| if (rsIsObject(pData->transform)) { |
| pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0); |
| } |
| |
| if (isDataOnly) { |
| // If we are a transform param and our transform is unchanged, nothing to do |
| if (pTransform) { |
| if (p->transformTimestamp == pTransform->timestamp) { |
| return false; |
| } |
| p->transformTimestamp = pTransform->timestamp; |
| } else { |
| if (p->dataTimestamp == pData->timestamp) { |
| return false; |
| } |
| p->dataTimestamp = pData->timestamp; |
| } |
| } |
| |
| const SgLight *pLight = NULL; |
| if (rsIsObject(pData->light)) { |
| pLight = (const SgLight *)rsGetElementAt(pData->light, 0); |
| } |
| |
| uint8_t *dataPtr = NULL; |
| const SgTexture *tex = NULL; |
| if (pData->type == SHADER_PARAM_TEXTURE) { |
| tex = rsGetElementAt(pData->texture, 0); |
| } else { |
| dataPtr = constantBuffer + p->bufferOffset; |
| } |
| |
| switch (pData->type) { |
| case SHADER_PARAM_TEXTURE: |
| rsgBindTexture(shader->program, p->bufferOffset, tex->texture); |
| break; |
| case SHADER_PARAM_FLOAT4_DATA: |
| writeFloatData((float*)dataPtr, &pData->float_value, p->float_vecSize); |
| break; |
| case SHADER_PARAM_FLOAT4_CAMERA_POS: |
| writeFloatData((float*)dataPtr, ¤tCam->position, p->float_vecSize); |
| break; |
| case SHADER_PARAM_FLOAT4_CAMERA_DIR: break; |
| case SHADER_PARAM_FLOAT4_LIGHT_COLOR: |
| writeFloatData((float*)dataPtr, &pLight->color, p->float_vecSize); |
| break; |
| case SHADER_PARAM_FLOAT4_LIGHT_POS: |
| writeFloatData((float*)dataPtr, &pLight->position, p->float_vecSize); |
| break; |
| case SHADER_PARAM_FLOAT4_LIGHT_DIR: break; |
| |
| case SHADER_PARAM_TRANSFORM_DATA: |
| rsMatrixLoad((rs_matrix4x4*)dataPtr, &pTransform->globalMat); |
| break; |
| case SHADER_PARAM_TRANSFORM_VIEW: |
| rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->view); |
| break; |
| case SHADER_PARAM_TRANSFORM_PROJ: |
| rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->proj); |
| break; |
| case SHADER_PARAM_TRANSFORM_VIEW_PROJ: |
| rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->viewProj); |
| break; |
| case SHADER_PARAM_TRANSFORM_MODEL: |
| rsMatrixLoad((rs_matrix4x4*)dataPtr, &pTransform->globalMat); |
| break; |
| case SHADER_PARAM_TRANSFORM_MODEL_VIEW: |
| rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->view); |
| rsMatrixLoadMultiply((rs_matrix4x4*)dataPtr, |
| (rs_matrix4x4*)dataPtr, |
| &pTransform->globalMat); |
| break; |
| case SHADER_PARAM_TRANSFORM_MODEL_VIEW_PROJ: |
| rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->viewProj); |
| rsMatrixLoadMultiply((rs_matrix4x4*)dataPtr, |
| (rs_matrix4x4*)dataPtr, |
| &pTransform->globalMat); |
| break; |
| } |
| return true; |
| } |
| |
| static inline void processAllParams(rs_allocation shaderConst, |
| rs_allocation allParams, |
| const SgCamera *camera) { |
| if (rsIsObject(shaderConst)) { |
| uint8_t *constantBuffer = (uint8_t*)rsGetElementAt(shaderConst, 0); |
| |
| int numParams = 0; |
| if (rsIsObject(allParams)) { |
| numParams = rsAllocationGetDimX(allParams); |
| } |
| bool updated = false; |
| for (int i = 0; i < numParams; i ++) { |
| SgShaderParam *current = (SgShaderParam*)rsGetElementAt(allParams, i); |
| SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0); |
| #ifdef DEBUG_PARAMS |
| debugParam(current, currentData); |
| #endif // DEBUG_PARAMS |
| updated = processParam(current, currentData, constantBuffer, camera, NULL) || updated; |
| } |
| } |
| } |
| |
| static inline void processTextureParams(SgFragmentShader *shader) { |
| int numParams = 0; |
| if (rsIsObject(shader->shaderTextureParams)) { |
| numParams = rsAllocationGetDimX(shader->shaderTextureParams); |
| } |
| for (int i = 0; i < numParams; i ++) { |
| SgShaderParam *current = (SgShaderParam*)rsGetElementAt(shader->shaderTextureParams, i); |
| SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0); |
| #ifdef DEBUG_PARAMS |
| debugParam(current, currentData); |
| #endif // DEBUG_PARAMS |
| processParam(current, currentData, NULL, NULL, shader); |
| } |
| } |