vertex.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /* libs/opengles/vertex.cpp
  2. **
  3. ** Copyright 2006, The Android Open Source Project
  4. **
  5. ** Licensed under the Apache License, Version 2.0 (the "License");
  6. ** you may not use this file except in compliance with the License.
  7. ** You may obtain a copy of the License at
  8. **
  9. ** http://www.apache.org/licenses/LICENSE-2.0
  10. **
  11. ** Unless required by applicable law or agreed to in writing, software
  12. ** distributed under the License is distributed on an "AS IS" BASIS,
  13. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ** See the License for the specific language governing permissions and
  15. ** limitations under the License.
  16. */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include "context.h"
  20. #include "fp.h"
  21. #include "vertex.h"
  22. #include "state.h"
  23. #include "matrix.h"
  24. namespace android {
  25. // ----------------------------------------------------------------------------
  26. void ogles_init_vertex(ogles_context_t* c)
  27. {
  28. c->cull.enable = GL_FALSE;
  29. c->cull.cullFace = GL_BACK;
  30. c->cull.frontFace = GL_CCW;
  31. c->current.color.r = 0x10000;
  32. c->current.color.g = 0x10000;
  33. c->current.color.b = 0x10000;
  34. c->current.color.a = 0x10000;
  35. c->currentNormal.z = 0x10000;
  36. }
  37. void ogles_uninit_vertex(ogles_context_t* /*c*/)
  38. {
  39. }
  40. // ----------------------------------------------------------------------------
  41. // vertex processing
  42. // ----------------------------------------------------------------------------
  43. // Divides a vertex clip coordinates by W
  44. static inline
  45. void perspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
  46. {
  47. // [x,y,z]window = vpt * ([x,y,z]clip / clip.w)
  48. // [w]window = 1/w
  49. // With a regular projection generated by glFrustum(),
  50. // we have w=-z, therefore, w is in [zNear, zFar].
  51. // Also, zNear and zFar are stricly positive,
  52. // and 1/w (window.w) is in [1/zFar, 1/zNear], usually this
  53. // means ]0, +inf[ -- however, it is always recommended
  54. // to use as large values as possible for zNear.
  55. // All in all, w is usually smaller than 1.0 (assuming
  56. // zNear is at least 1.0); and even if zNear is smaller than 1.0
  57. // values of w won't be too big.
  58. const int32_t rw = gglRecip28(v->clip.w);
  59. const GLfixed* const m = c->transforms.vpt.transform.matrix.m;
  60. v->window.w = rw;
  61. v->window.x = gglMulAddx(gglMulx(v->clip.x, rw, 16), m[ 0], m[12], 28);
  62. v->window.y = gglMulAddx(gglMulx(v->clip.y, rw, 16), m[ 5], m[13], 28);
  63. v->window.x = TRI_FROM_FIXED(v->window.x);
  64. v->window.y = TRI_FROM_FIXED(v->window.y);
  65. if (enables & GGL_ENABLE_DEPTH_TEST) {
  66. v->window.z = gglMulAddx(gglMulx(v->clip.z, rw, 16), m[10], m[14], 28);
  67. }
  68. }
  69. // frustum clipping and W-divide
  70. static inline
  71. void clipFrustumPerspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
  72. {
  73. // ndc = clip / W
  74. // window = ncd * viewport
  75. // clip to the view-volume
  76. uint32_t clip = v->flags & vertex_t::CLIP_ALL;
  77. const GLfixed w = v->clip.w;
  78. if (v->clip.x < -w) clip |= vertex_t::CLIP_L;
  79. if (v->clip.x > w) clip |= vertex_t::CLIP_R;
  80. if (v->clip.y < -w) clip |= vertex_t::CLIP_B;
  81. if (v->clip.y > w) clip |= vertex_t::CLIP_T;
  82. if (v->clip.z < -w) clip |= vertex_t::CLIP_N;
  83. if (v->clip.z > w) clip |= vertex_t::CLIP_F;
  84. v->flags |= clip;
  85. c->arrays.cull &= clip;
  86. if (ggl_likely(!clip)) {
  87. // if the vertex is clipped, we don't do the perspective
  88. // divide, since we don't need its window coordinates.
  89. perspective(c, v, enables);
  90. }
  91. }
  92. // frustum clipping, user clipping and W-divide
  93. static inline
  94. void clipAllPerspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
  95. {
  96. // compute eye coordinates
  97. c->arrays.mv_transform(
  98. &c->transforms.modelview.transform, &v->eye, &v->obj);
  99. v->flags |= vertex_t::EYE;
  100. // clip this vertex against each user clip plane
  101. uint32_t clip = 0;
  102. int planes = c->clipPlanes.enable;
  103. while (planes) {
  104. const int i = 31 - gglClz(planes);
  105. planes &= ~(1<<i);
  106. // XXX: we should have a special dot() for 2,3,4 coords vertices
  107. GLfixed d = dot4(c->clipPlanes.plane[i].equation.v, v->eye.v);
  108. if (d < 0) {
  109. clip |= 0x100<<i;
  110. }
  111. }
  112. v->flags |= clip;
  113. clipFrustumPerspective(c, v, enables);
  114. }
  115. // ----------------------------------------------------------------------------
  116. void ogles_vertex_project(ogles_context_t* c, vertex_t* v) {
  117. perspective(c, v, c->rasterizer.state.enables);
  118. }
  119. void ogles_vertex_perspective2D(ogles_context_t* c, vertex_t* v)
  120. {
  121. // here we assume w=1.0 and the viewport transformation
  122. // has been applied already.
  123. c->arrays.cull = 0;
  124. v->window.x = TRI_FROM_FIXED(v->clip.x);
  125. v->window.y = TRI_FROM_FIXED(v->clip.y);
  126. v->window.z = v->clip.z;
  127. v->window.w = v->clip.w << 12;
  128. }
  129. void ogles_vertex_perspective3DZ(ogles_context_t* c, vertex_t* v) {
  130. clipFrustumPerspective(c, v, GGL_ENABLE_DEPTH_TEST);
  131. }
  132. void ogles_vertex_perspective3D(ogles_context_t* c, vertex_t* v) {
  133. clipFrustumPerspective(c, v, 0);
  134. }
  135. void ogles_vertex_clipAllPerspective3DZ(ogles_context_t* c, vertex_t* v) {
  136. clipAllPerspective(c, v, GGL_ENABLE_DEPTH_TEST);
  137. }
  138. void ogles_vertex_clipAllPerspective3D(ogles_context_t* c, vertex_t* v) {
  139. clipAllPerspective(c, v, 0);
  140. }
  141. static void clipPlanex(GLenum plane, const GLfixed* equ, ogles_context_t* c)
  142. {
  143. const int p = plane - GL_CLIP_PLANE0;
  144. if (ggl_unlikely(uint32_t(p) > (GL_CLIP_PLANE5 - GL_CLIP_PLANE0))) {
  145. ogles_error(c, GL_INVALID_ENUM);
  146. return;
  147. }
  148. vec4_t& equation = c->clipPlanes.plane[p].equation;
  149. memcpy(equation.v, equ, sizeof(vec4_t));
  150. ogles_validate_transform(c, transform_state_t::MVIT);
  151. transform_t& mvit = c->transforms.mvit4;
  152. mvit.point4(&mvit, &equation, &equation);
  153. }
  154. // ----------------------------------------------------------------------------
  155. }; // namespace android
  156. // ----------------------------------------------------------------------------
  157. using namespace android;
  158. void glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
  159. {
  160. ogles_context_t* c = ogles_context_t::get();
  161. c->current.color.r = gglFloatToFixed(r);
  162. c->currentColorClamped.r = gglClampx(c->current.color.r);
  163. c->current.color.g = gglFloatToFixed(g);
  164. c->currentColorClamped.g = gglClampx(c->current.color.g);
  165. c->current.color.b = gglFloatToFixed(b);
  166. c->currentColorClamped.b = gglClampx(c->current.color.b);
  167. c->current.color.a = gglFloatToFixed(a);
  168. c->currentColorClamped.a = gglClampx(c->current.color.a);
  169. }
  170. void glColor4x(GLfixed r, GLfixed g, GLfixed b, GLfixed a)
  171. {
  172. ogles_context_t* c = ogles_context_t::get();
  173. c->current.color.r = r;
  174. c->current.color.g = g;
  175. c->current.color.b = b;
  176. c->current.color.a = a;
  177. c->currentColorClamped.r = gglClampx(r);
  178. c->currentColorClamped.g = gglClampx(g);
  179. c->currentColorClamped.b = gglClampx(b);
  180. c->currentColorClamped.a = gglClampx(a);
  181. }
  182. void glNormal3f(GLfloat x, GLfloat y, GLfloat z)
  183. {
  184. ogles_context_t* c = ogles_context_t::get();
  185. c->currentNormal.x = gglFloatToFixed(x);
  186. c->currentNormal.y = gglFloatToFixed(y);
  187. c->currentNormal.z = gglFloatToFixed(z);
  188. }
  189. void glNormal3x(GLfixed x, GLfixed y, GLfixed z)
  190. {
  191. ogles_context_t* c = ogles_context_t::get();
  192. c->currentNormal.x = x;
  193. c->currentNormal.y = y;
  194. c->currentNormal.z = z;
  195. }
  196. // ----------------------------------------------------------------------------
  197. void glClipPlanef(GLenum plane, const GLfloat* equ)
  198. {
  199. const GLfixed equx[4] = {
  200. gglFloatToFixed(equ[0]),
  201. gglFloatToFixed(equ[1]),
  202. gglFloatToFixed(equ[2]),
  203. gglFloatToFixed(equ[3])
  204. };
  205. ogles_context_t* c = ogles_context_t::get();
  206. clipPlanex(plane, equx, c);
  207. }
  208. void glClipPlanex(GLenum plane, const GLfixed* equ)
  209. {
  210. ogles_context_t* c = ogles_context_t::get();
  211. clipPlanex(plane, equ, c);
  212. }