1 // Copyright (C) 2011-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 "rs_graphics.rsh"
20 #include "scenegraph_objects.rsh"
21 
22 rs_script gTransformScript;
23 rs_script gCameraScript;
24 rs_script gLightScript;
25 rs_script gObjectParamsScript;
26 rs_script gFragmentParamsScript;
27 rs_script gVertexParamsScript;
28 rs_script gCullScript;
29 
30 SgTransform *gRootNode;
31 rs_allocation gCameras;
32 rs_allocation gLights;
33 rs_allocation gFragmentShaders;
34 rs_allocation gVertexShaders;
35 rs_allocation gRenderableObjects;
36 
37 rs_allocation gRenderPasses;
38 
39 // Temporary shaders
40 rs_program_store gPFSBackground;
41 
42 uint32_t *gFrontToBack;
43 static uint32_t gFrontToBackCount = 0;
44 uint32_t *gBackToFront;
45 static uint32_t gBackToFrontCount = 0;
46 
47 static SgCamera *gActiveCamera = NULL;
48 
49 static rs_allocation nullAlloc;
50 
51 // #define DEBUG_RENDERABLES
52 static void draw(SgRenderable *obj) {
53 #ifdef DEBUG_RENDERABLES
54     const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0);
55     rsDebug("**** Drawing object with transform", obj);
56     printName(objTransform->name);
57     rsDebug("Model matrix: ", &objTransform->globalMat);
58     printName(obj->name);
59 #endif //DEBUG_RENDERABLES
60 
61     const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0);
62     const SgVertexShader *pv = (const SgVertexShader *)rsGetElementAt(renderState->pv, 0);
63     const SgFragmentShader *pf = (const SgFragmentShader *)rsGetElementAt(renderState->pf, 0);
64 
65     if (pv->objectConstIndex != -1) {
66         rsgBindConstant(pv->program, pv->objectConstIndex, obj->pv_const);
67     }
68     if (pf->objectConstIndex != -1) {
69         rsgBindConstant(pf->program, pf->objectConstIndex, obj->pf_const);
70     }
71 
72     if (rsIsObject(renderState->ps)) {
73         rsgBindProgramStore(renderState->ps);
74     } else {
75         rsgBindProgramStore(gPFSBackground);
76     }
77 
78     if (rsIsObject(renderState->pr)) {
79         rsgBindProgramRaster(renderState->pr);
80     } else {
81         rs_program_raster pr = {0};
82         rsgBindProgramRaster(pr);
83     }
84 
85     rsgBindProgramVertex(pv->program);
86     rsgBindProgramFragment(pf->program);
87 
88     for (uint32_t i = 0; i < obj->pf_num_textures; i ++) {
89         const SgTexture *tex = rsGetElementAt(obj->pf_textures[i], 0);
90         rsgBindTexture(pf->program, i, tex->texture);
91     }
92 
93     rsgDrawMesh(obj->mesh, obj->meshIndex);
94 }
95 
96 static void sortToBucket(SgRenderable *obj) {
97     const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0);
98     if (rsIsObject(renderState->ps)) {
99         bool isOpaque = false;
100         if (isOpaque) {
101             gFrontToBack[gFrontToBackCount++] = (uint32_t)obj;
102         } else {
103             gBackToFront[gBackToFrontCount++] = (uint32_t)obj;
104         }
105     } else {
106         gFrontToBack[gFrontToBackCount++] = (uint32_t)obj;
107     }
108 }
109 
110 static void updateActiveCamera(rs_allocation cam) {
111     gActiveCamera = (SgCamera *)rsGetElementAt(cam, 0);
112 }
113 
114 static void prepareCameras() {
115     // now compute all the camera matrices
116     if (rsIsObject(gCameras)) {
117         float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
118         rsForEach(gCameraScript, gCameras, nullAlloc, &aspect, sizeof(aspect));
119     }
120 }
121 
122 static void prepareLights() {
123     if (rsIsObject(gLights)) {
124         rsForEach(gLightScript, gLights, nullAlloc);
125     }
126 }
127 
128 static void drawSorted() {
129     for (int i = 0; i < gFrontToBackCount; i ++) {
130         SgRenderable *current = (SgRenderable*)gFrontToBack[i];
131         draw(current);
132     }
133 
134     for (int i = 0; i < gBackToFrontCount; i ++) {
135         SgRenderable *current = (SgRenderable*)gBackToFront[i];
136         draw(current);
137     }
138 }
139 
140 static void drawAllObjects(rs_allocation allObj) {
141     if (!rsIsObject(allObj)) {
142         return;
143     }
144 
145     if (rsIsObject(gVertexShaders)) {
146         rsForEach(gVertexParamsScript, nullAlloc, gVertexShaders,
147                   gActiveCamera, sizeof(gActiveCamera));
148     }
149     if (rsIsObject(gFragmentShaders)) {
150         rsForEach(gFragmentParamsScript, nullAlloc, gFragmentShaders,
151                   gActiveCamera, sizeof(gActiveCamera));
152     }
153 
154     // Run the params and cull script
155     rsForEach(gCullScript, nullAlloc, allObj, gActiveCamera, sizeof(gActiveCamera));
156     rsForEach(gObjectParamsScript, nullAlloc, allObj, gActiveCamera, sizeof(gActiveCamera));
157 
158     int numRenderables = rsAllocationGetDimX(allObj);
159     for (int i = 0; i < numRenderables; i ++) {
160         rs_allocation *drawAlloc = (rs_allocation*)rsGetElementAt(allObj, i);
161         SgRenderable *current = (SgRenderable*)rsGetElementAt(*drawAlloc, 0);
162         if (current->isVisible) {
163             sortToBucket(current);
164         }
165     }
166     drawSorted();
167 }
168 
169 int root(void) {
170 #ifdef DEBUG_RENDERABLES
171     rsDebug("=============================================================================", 0);
172 #endif // DEBUG_RENDERABLES
173 
174     // first step is to update the transform hierachy
175     if (gRootNode && rsIsObject(gRootNode->children)) {
176         rsForEach(gTransformScript, gRootNode->children, nullAlloc, 0, 0);
177     }
178 
179     prepareCameras();
180     prepareLights();
181 
182     if (rsIsObject(gRenderPasses)) {
183         rsgClearDepth(1.0f);
184         int numPasses = rsAllocationGetDimX(gRenderPasses);
185         for (uint i = 0; i < numPasses; i ++) {
186             gFrontToBackCount = 0;
187             gBackToFrontCount = 0;
188             SgRenderPass *pass = (SgRenderPass*)rsGetElementAt(gRenderPasses, i);
189             if (rsIsObject(pass->color_target)) {
190                 rsgBindColorTarget(pass->color_target, 0);
191             }
192             if (rsIsObject(pass->depth_target)) {
193                 rsgBindDepthTarget(pass->depth_target);
194             }
195             if (!rsIsObject(pass->color_target) &&
196                 !rsIsObject(pass->depth_target)) {
197                 rsgClearAllRenderTargets();
198             }
199             updateActiveCamera(pass->camera);
200             if (pass->should_clear_color) {
201                 rsgClearColor(pass->clear_color.x, pass->clear_color.y,
202                               pass->clear_color.z, pass->clear_color.w);
203             }
204             if (pass->should_clear_depth) {
205                 rsgClearDepth(pass->clear_depth);
206             }
207             drawAllObjects(pass->objects);
208         }
209     } else {
210         gFrontToBackCount = 0;
211         gBackToFrontCount = 0;
212         rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
213         rsgClearDepth(1.0f);
214 
215         if (rsIsObject(gCameras)) {
216             rs_allocation *camAlloc = (rs_allocation*)rsGetElementAt(gCameras, 0);
217             updateActiveCamera(*camAlloc);
218         }
219         drawAllObjects(gRenderableObjects);
220     }
221     return 10;
222 }
223 
224 // Search through sorted and culled objects
225 void pick(int screenX, int screenY) {
226     float3 pnt, vec;
227     getCameraRay(gActiveCamera, screenX, screenY, &pnt, &vec);
228 
229     for (int i = 0; i < gFrontToBackCount; i ++) {
230         SgRenderable *current = (SgRenderable*)gFrontToBack[i];
231         bool isPicked = intersect(current, pnt, vec);
232         if (isPicked) {
233             current->cullType = CULL_ALWAYS;
234         }
235     }
236 
237     for (int i = 0; i < gBackToFrontCount; i ++) {
238         SgRenderable *current = (SgRenderable*)gBackToFront[i];
239         bool isPicked = intersect(current, pnt, vec);
240         if (isPicked) {
241             current->cullType = CULL_ALWAYS;
242         }
243     }
244 }
245