1// Copyright (C) 2012 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma version(1)
16
17#pragma rs java_package_name(com.android.scenegraph)
18
19#include "scenegraph_objects.rsh"
20
21//#define DEBUG_PARAMS
22static void debugParam(SgShaderParam *p, SgShaderParamData *pData) {
23    rsDebug("____________ Param ____________", p);
24    printName(pData->paramName);
25    rsDebug("bufferOffset", p->bufferOffset);
26    rsDebug("type ", pData->type);
27    rsDebug("data timestamp ", pData->timestamp);
28    rsDebug("param timestamp", p->dataTimestamp);
29
30    const SgTransform *pTransform = NULL;
31    if (rsIsObject(pData->transform)) {
32        pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0);
33
34        rsDebug("transform", pTransform);
35        printName(pTransform->name);
36        rsDebug("timestamp", pTransform->timestamp);
37        rsDebug("param timestamp", p->transformTimestamp);
38    }
39
40    const SgLight *pLight = NULL;
41    if (rsIsObject(pData->light)) {
42        pLight = (const SgLight *)rsGetElementAt(pData->light, 0);
43        printLightInfo(pLight);
44    }
45}
46
47
48static void writeFloatData(float *ptr, const float4 *input, uint32_t vecSize) {
49#ifdef DEBUG_PARAMS
50    rsDebug("Writing value ", *input);
51    rsDebug("Writing vec size ", vecSize);
52#endif // DEBUG_PARAMS
53
54    switch (vecSize) {
55    case 1:
56        *ptr = input->x;
57        break;
58    case 2:
59        *((float2*)ptr) = (*input).xy;
60        break;
61    case 3:
62        *((float3*)ptr) = (*input).xyz;
63        break;
64    case 4:
65        *((float4*)ptr) = *input;
66        break;
67    }
68}
69
70static bool processParam(SgShaderParam *p, SgShaderParamData *pData,
71                         uint8_t *constantBuffer,
72                         const SgCamera *currentCam,
73                         SgFragmentShader *shader) {
74    bool isDataOnly = (pData->type > SHADER_PARAM_DATA_ONLY);
75    const SgTransform *pTransform = NULL;
76    if (rsIsObject(pData->transform)) {
77        pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0);
78    }
79
80    if (isDataOnly) {
81        // If we are a transform param and our transform is unchanged, nothing to do
82        if (pTransform) {
83            if (p->transformTimestamp == pTransform->timestamp) {
84                return false;
85            }
86            p->transformTimestamp = pTransform->timestamp;
87        } else {
88            if (p->dataTimestamp == pData->timestamp) {
89                return false;
90            }
91            p->dataTimestamp = pData->timestamp;
92        }
93    }
94
95    const SgLight *pLight = NULL;
96    if (rsIsObject(pData->light)) {
97        pLight = (const SgLight *)rsGetElementAt(pData->light, 0);
98    }
99
100    uint8_t *dataPtr = NULL;
101    const SgTexture *tex = NULL;
102    if (pData->type == SHADER_PARAM_TEXTURE) {
103        tex = rsGetElementAt(pData->texture, 0);
104    } else {
105        dataPtr = constantBuffer + p->bufferOffset;
106    }
107
108    switch (pData->type) {
109    case SHADER_PARAM_TEXTURE:
110        rsgBindTexture(shader->program, p->bufferOffset, tex->texture);
111        break;
112    case SHADER_PARAM_FLOAT4_DATA:
113        writeFloatData((float*)dataPtr, &pData->float_value, p->float_vecSize);
114        break;
115    case SHADER_PARAM_FLOAT4_CAMERA_POS:
116        writeFloatData((float*)dataPtr, &currentCam->position, p->float_vecSize);
117        break;
118    case SHADER_PARAM_FLOAT4_CAMERA_DIR: break;
119    case SHADER_PARAM_FLOAT4_LIGHT_COLOR:
120        writeFloatData((float*)dataPtr, &pLight->color, p->float_vecSize);
121        break;
122    case SHADER_PARAM_FLOAT4_LIGHT_POS:
123        writeFloatData((float*)dataPtr, &pLight->position, p->float_vecSize);
124        break;
125    case SHADER_PARAM_FLOAT4_LIGHT_DIR: break;
126
127    case SHADER_PARAM_TRANSFORM_DATA:
128        rsMatrixLoad((rs_matrix4x4*)dataPtr, &pTransform->globalMat);
129        break;
130    case SHADER_PARAM_TRANSFORM_VIEW:
131        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->view);
132        break;
133    case SHADER_PARAM_TRANSFORM_PROJ:
134        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->proj);
135        break;
136    case SHADER_PARAM_TRANSFORM_VIEW_PROJ:
137        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->viewProj);
138        break;
139    case SHADER_PARAM_TRANSFORM_MODEL:
140        rsMatrixLoad((rs_matrix4x4*)dataPtr, &pTransform->globalMat);
141        break;
142    case SHADER_PARAM_TRANSFORM_MODEL_VIEW:
143        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->view);
144        rsMatrixLoadMultiply((rs_matrix4x4*)dataPtr,
145                             (rs_matrix4x4*)dataPtr,
146                             &pTransform->globalMat);
147        break;
148    case SHADER_PARAM_TRANSFORM_MODEL_VIEW_PROJ:
149        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->viewProj);
150        rsMatrixLoadMultiply((rs_matrix4x4*)dataPtr,
151                             (rs_matrix4x4*)dataPtr,
152                             &pTransform->globalMat);
153        break;
154    }
155    return true;
156}
157
158static void processAllParams(rs_allocation shaderConst,
159                             rs_allocation allParams,
160                             const SgCamera *camera) {
161    if (rsIsObject(shaderConst)) {
162        uint8_t *constantBuffer = (uint8_t*)rsGetElementAt(shaderConst, 0);
163
164        int numParams = 0;
165        if (rsIsObject(allParams)) {
166            numParams = rsAllocationGetDimX(allParams);
167        }
168        bool updated = false;
169        for (int i = 0; i < numParams; i ++) {
170            SgShaderParam *current = (SgShaderParam*)rsGetElementAt(allParams, i);
171            SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0);
172#ifdef DEBUG_PARAMS
173            debugParam(current, currentData);
174#endif // DEBUG_PARAMS
175            updated = processParam(current, currentData, constantBuffer, camera, NULL) || updated;
176        }
177    }
178}
179
180static void processTextureParams(SgFragmentShader *shader) {
181    int numParams = 0;
182    if (rsIsObject(shader->shaderTextureParams)) {
183        numParams = rsAllocationGetDimX(shader->shaderTextureParams);
184    }
185    for (int i = 0; i < numParams; i ++) {
186        SgShaderParam *current = (SgShaderParam*)rsGetElementAt(shader->shaderTextureParams, i);
187        SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0);
188#ifdef DEBUG_PARAMS
189        debugParam(current, currentData);
190#endif // DEBUG_PARAMS
191        processParam(current, currentData, NULL, NULL, shader);
192    }
193}
194