Clone of mesa.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

s_blend.c 32KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. /*
  2. * Mesa 3-D graphics library
  3. * Version: 7.1
  4. *
  5. * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. /**
  25. * \file swrast/s_blend.c
  26. * \brief software blending.
  27. * \author Brian Paul
  28. *
  29. * Only a few blend modes have been optimized (min, max, transparency, add)
  30. * more optimized cases can easily be added if needed.
  31. * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example.
  32. */
  33. #include "main/glheader.h"
  34. #include "main/context.h"
  35. #include "main/colormac.h"
  36. #include "main/macros.h"
  37. #include "s_blend.h"
  38. #include "s_context.h"
  39. #include "s_span.h"
  40. #if defined(USE_MMX_ASM)
  41. #include "x86/mmx.h"
  42. #include "x86/common_x86_asm.h"
  43. #define _BLENDAPI _ASMAPI
  44. #else
  45. #define _BLENDAPI
  46. #endif
  47. /**
  48. * Integer divide by 255
  49. * Declare "int divtemp" before using.
  50. * This satisfies Glean and should be reasonably fast.
  51. * Contributed by Nathan Hand.
  52. */
  53. #define DIV255(X) (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16)
  54. /**
  55. * Special case for glBlendFunc(GL_ZERO, GL_ONE).
  56. * No-op means the framebuffer values remain unchanged.
  57. * Any chanType ok.
  58. */
  59. static void _BLENDAPI
  60. blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  61. GLvoid *src, const GLvoid *dst, GLenum chanType)
  62. {
  63. GLint bytes;
  64. ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
  65. ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
  66. ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ZERO);
  67. ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
  68. (void) ctx;
  69. /* just memcpy */
  70. if (chanType == GL_UNSIGNED_BYTE)
  71. bytes = 4 * n * sizeof(GLubyte);
  72. else if (chanType == GL_UNSIGNED_SHORT)
  73. bytes = 4 * n * sizeof(GLushort);
  74. else
  75. bytes = 4 * n * sizeof(GLfloat);
  76. memcpy(src, dst, bytes);
  77. }
  78. /**
  79. * Special case for glBlendFunc(GL_ONE, GL_ZERO)
  80. * Any chanType ok.
  81. */
  82. static void _BLENDAPI
  83. blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  84. GLvoid *src, const GLvoid *dst, GLenum chanType)
  85. {
  86. ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
  87. ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
  88. ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
  89. ASSERT(ctx->Color.Blend[0].DstRGB == GL_ZERO);
  90. (void) ctx;
  91. (void) n;
  92. (void) mask;
  93. (void) src;
  94. (void) dst;
  95. }
  96. /**
  97. * Common transparency blending mode:
  98. * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
  99. */
  100. static void _BLENDAPI
  101. blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  102. GLvoid *src, const GLvoid *dst, GLenum chanType)
  103. {
  104. GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
  105. const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
  106. GLuint i;
  107. ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
  108. ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
  109. ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
  110. ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
  111. ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
  112. ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
  113. ASSERT(chanType == GL_UNSIGNED_BYTE);
  114. (void) ctx;
  115. for (i = 0; i < n; i++) {
  116. if (mask[i]) {
  117. const GLint t = rgba[i][ACOMP]; /* t is in [0, 255] */
  118. if (t == 0) {
  119. /* 0% alpha */
  120. COPY_4UBV(rgba[i], dest[i]);
  121. }
  122. else if (t != 255) {
  123. GLint divtemp;
  124. const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
  125. const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
  126. const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
  127. const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP];
  128. ASSERT(r <= 255);
  129. ASSERT(g <= 255);
  130. ASSERT(b <= 255);
  131. ASSERT(a <= 255);
  132. rgba[i][RCOMP] = (GLubyte) r;
  133. rgba[i][GCOMP] = (GLubyte) g;
  134. rgba[i][BCOMP] = (GLubyte) b;
  135. rgba[i][ACOMP] = (GLubyte) a;
  136. }
  137. }
  138. }
  139. }
  140. static void _BLENDAPI
  141. blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  142. GLvoid *src, const GLvoid *dst, GLenum chanType)
  143. {
  144. GLushort (*rgba)[4] = (GLushort (*)[4]) src;
  145. const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
  146. GLuint i;
  147. ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
  148. ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
  149. ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
  150. ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
  151. ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
  152. ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
  153. ASSERT(chanType == GL_UNSIGNED_SHORT);
  154. (void) ctx;
  155. for (i = 0; i < n; i++) {
  156. if (mask[i]) {
  157. const GLint t = rgba[i][ACOMP];
  158. if (t == 0) {
  159. /* 0% alpha */
  160. COPY_4V(rgba[i], dest[i]);
  161. }
  162. else if (t != 65535) {
  163. const GLfloat tt = (GLfloat) t / 65535.0F;
  164. GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
  165. GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
  166. GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
  167. GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
  168. ASSIGN_4V(rgba[i], r, g, b, a);
  169. }
  170. }
  171. }
  172. }
  173. static void _BLENDAPI
  174. blend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  175. GLvoid *src, const GLvoid *dst, GLenum chanType)
  176. {
  177. GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
  178. const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
  179. GLuint i;
  180. ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
  181. ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
  182. ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
  183. ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
  184. ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
  185. ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
  186. ASSERT(chanType == GL_FLOAT);
  187. (void) ctx;
  188. for (i = 0; i < n; i++) {
  189. if (mask[i]) {
  190. const GLfloat t = rgba[i][ACOMP]; /* t in [0, 1] */
  191. if (t == 0.0F) {
  192. /* 0% alpha */
  193. COPY_4V(rgba[i], dest[i]);
  194. }
  195. else if (t != 1.0F) {
  196. GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP];
  197. GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP];
  198. GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP];
  199. GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP];
  200. ASSIGN_4V(rgba[i], r, g, b, a);
  201. }
  202. }
  203. }
  204. }
  205. /**
  206. * Add src and dest: glBlendFunc(GL_ONE, GL_ONE).
  207. * Any chanType ok.
  208. */
  209. static void _BLENDAPI
  210. blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  211. GLvoid *src, const GLvoid *dst, GLenum chanType)
  212. {
  213. GLuint i;
  214. ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
  215. ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
  216. ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
  217. ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
  218. (void) ctx;
  219. if (chanType == GL_UNSIGNED_BYTE) {
  220. GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
  221. const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
  222. for (i=0;i<n;i++) {
  223. if (mask[i]) {
  224. GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
  225. GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
  226. GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
  227. GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
  228. rgba[i][RCOMP] = (GLubyte) MIN2( r, 255 );
  229. rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 );
  230. rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 );
  231. rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 );
  232. }
  233. }
  234. }
  235. else if (chanType == GL_UNSIGNED_SHORT) {
  236. GLushort (*rgba)[4] = (GLushort (*)[4]) src;
  237. const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
  238. for (i=0;i<n;i++) {
  239. if (mask[i]) {
  240. GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
  241. GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
  242. GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
  243. GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
  244. rgba[i][RCOMP] = (GLshort) MIN2( r, 255 );
  245. rgba[i][GCOMP] = (GLshort) MIN2( g, 255 );
  246. rgba[i][BCOMP] = (GLshort) MIN2( b, 255 );
  247. rgba[i][ACOMP] = (GLshort) MIN2( a, 255 );
  248. }
  249. }
  250. }
  251. else {
  252. GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
  253. const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
  254. ASSERT(chanType == GL_FLOAT);
  255. for (i=0;i<n;i++) {
  256. if (mask[i]) {
  257. /* don't RGB clamp to max */
  258. rgba[i][RCOMP] += dest[i][RCOMP];
  259. rgba[i][GCOMP] += dest[i][GCOMP];
  260. rgba[i][BCOMP] += dest[i][BCOMP];
  261. rgba[i][ACOMP] += dest[i][ACOMP];
  262. }
  263. }
  264. }
  265. }
  266. /**
  267. * Blend min function.
  268. * Any chanType ok.
  269. */
  270. static void _BLENDAPI
  271. blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  272. GLvoid *src, const GLvoid *dst, GLenum chanType)
  273. {
  274. GLuint i;
  275. ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MIN);
  276. ASSERT(ctx->Color.Blend[0].EquationA == GL_MIN);
  277. (void) ctx;
  278. if (chanType == GL_UNSIGNED_BYTE) {
  279. GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
  280. const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
  281. for (i=0;i<n;i++) {
  282. if (mask[i]) {
  283. rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
  284. rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
  285. rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
  286. rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
  287. }
  288. }
  289. }
  290. else if (chanType == GL_UNSIGNED_SHORT) {
  291. GLushort (*rgba)[4] = (GLushort (*)[4]) src;
  292. const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
  293. for (i=0;i<n;i++) {
  294. if (mask[i]) {
  295. rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
  296. rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
  297. rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
  298. rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
  299. }
  300. }
  301. }
  302. else {
  303. GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
  304. const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
  305. ASSERT(chanType == GL_FLOAT);
  306. for (i=0;i<n;i++) {
  307. if (mask[i]) {
  308. rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
  309. rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
  310. rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
  311. rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
  312. }
  313. }
  314. }
  315. }
  316. /**
  317. * Blend max function.
  318. * Any chanType ok.
  319. */
  320. static void _BLENDAPI
  321. blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  322. GLvoid *src, const GLvoid *dst, GLenum chanType)
  323. {
  324. GLuint i;
  325. ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MAX);
  326. ASSERT(ctx->Color.Blend[0].EquationA == GL_MAX);
  327. (void) ctx;
  328. if (chanType == GL_UNSIGNED_BYTE) {
  329. GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
  330. const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
  331. for (i=0;i<n;i++) {
  332. if (mask[i]) {
  333. rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
  334. rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
  335. rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
  336. rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
  337. }
  338. }
  339. }
  340. else if (chanType == GL_UNSIGNED_SHORT) {
  341. GLushort (*rgba)[4] = (GLushort (*)[4]) src;
  342. const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
  343. for (i=0;i<n;i++) {
  344. if (mask[i]) {
  345. rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
  346. rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
  347. rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
  348. rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
  349. }
  350. }
  351. }
  352. else {
  353. GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
  354. const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
  355. ASSERT(chanType == GL_FLOAT);
  356. for (i=0;i<n;i++) {
  357. if (mask[i]) {
  358. rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
  359. rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
  360. rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
  361. rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
  362. }
  363. }
  364. }
  365. }
  366. /**
  367. * Modulate: result = src * dest
  368. * Any chanType ok.
  369. */
  370. static void _BLENDAPI
  371. blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  372. GLvoid *src, const GLvoid *dst, GLenum chanType)
  373. {
  374. GLuint i;
  375. (void) ctx;
  376. if (chanType == GL_UNSIGNED_BYTE) {
  377. GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
  378. const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
  379. for (i=0;i<n;i++) {
  380. if (mask[i]) {
  381. GLint divtemp;
  382. rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]);
  383. rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]);
  384. rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]);
  385. rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]);
  386. }
  387. }
  388. }
  389. else if (chanType == GL_UNSIGNED_SHORT) {
  390. GLushort (*rgba)[4] = (GLushort (*)[4]) src;
  391. const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
  392. for (i=0;i<n;i++) {
  393. if (mask[i]) {
  394. rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
  395. rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
  396. rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
  397. rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
  398. }
  399. }
  400. }
  401. else {
  402. GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
  403. const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
  404. ASSERT(chanType == GL_FLOAT);
  405. for (i=0;i<n;i++) {
  406. if (mask[i]) {
  407. rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
  408. rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
  409. rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
  410. rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
  411. }
  412. }
  413. }
  414. }
  415. /**
  416. * Do any blending operation, using floating point.
  417. * \param n number of pixels
  418. * \param mask fragment writemask array
  419. * \param rgba array of incoming (and modified) pixels
  420. * \param dest array of pixels from the dest color buffer
  421. */
  422. static void
  423. blend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  424. GLfloat rgba[][4], GLfloat dest[][4],
  425. GLenum chanType)
  426. {
  427. GLuint i;
  428. for (i = 0; i < n; i++) {
  429. if (mask[i]) {
  430. /* Incoming/source Color */
  431. const GLfloat Rs = rgba[i][RCOMP];
  432. const GLfloat Gs = rgba[i][GCOMP];
  433. const GLfloat Bs = rgba[i][BCOMP];
  434. const GLfloat As = rgba[i][ACOMP];
  435. /* Frame buffer/dest color */
  436. const GLfloat Rd = dest[i][RCOMP];
  437. const GLfloat Gd = dest[i][GCOMP];
  438. const GLfloat Bd = dest[i][BCOMP];
  439. const GLfloat Ad = dest[i][ACOMP];
  440. GLfloat sR, sG, sB, sA; /* Source factor */
  441. GLfloat dR, dG, dB, dA; /* Dest factor */
  442. GLfloat r, g, b, a; /* result color */
  443. /* XXX for the case of constant blend terms we could init
  444. * the sX and dX variables just once before the loop.
  445. */
  446. /* Source RGB factor */
  447. switch (ctx->Color.Blend[0].SrcRGB) {
  448. case GL_ZERO:
  449. sR = sG = sB = 0.0F;
  450. break;
  451. case GL_ONE:
  452. sR = sG = sB = 1.0F;
  453. break;
  454. case GL_DST_COLOR:
  455. sR = Rd;
  456. sG = Gd;
  457. sB = Bd;
  458. break;
  459. case GL_ONE_MINUS_DST_COLOR:
  460. sR = 1.0F - Rd;
  461. sG = 1.0F - Gd;
  462. sB = 1.0F - Bd;
  463. break;
  464. case GL_SRC_ALPHA:
  465. sR = sG = sB = As;
  466. break;
  467. case GL_ONE_MINUS_SRC_ALPHA:
  468. sR = sG = sB = 1.0F - As;
  469. break;
  470. case GL_DST_ALPHA:
  471. sR = sG = sB = Ad;
  472. break;
  473. case GL_ONE_MINUS_DST_ALPHA:
  474. sR = sG = sB = 1.0F - Ad;
  475. break;
  476. case GL_SRC_ALPHA_SATURATE:
  477. if (As < 1.0F - Ad) {
  478. sR = sG = sB = As;
  479. }
  480. else {
  481. sR = sG = sB = 1.0F - Ad;
  482. }
  483. break;
  484. case GL_CONSTANT_COLOR:
  485. sR = ctx->Color.BlendColor[0];
  486. sG = ctx->Color.BlendColor[1];
  487. sB = ctx->Color.BlendColor[2];
  488. break;
  489. case GL_ONE_MINUS_CONSTANT_COLOR:
  490. sR = 1.0F - ctx->Color.BlendColor[0];
  491. sG = 1.0F - ctx->Color.BlendColor[1];
  492. sB = 1.0F - ctx->Color.BlendColor[2];
  493. break;
  494. case GL_CONSTANT_ALPHA:
  495. sR = sG = sB = ctx->Color.BlendColor[3];
  496. break;
  497. case GL_ONE_MINUS_CONSTANT_ALPHA:
  498. sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
  499. break;
  500. case GL_SRC_COLOR:
  501. sR = Rs;
  502. sG = Gs;
  503. sB = Bs;
  504. break;
  505. case GL_ONE_MINUS_SRC_COLOR:
  506. sR = 1.0F - Rs;
  507. sG = 1.0F - Gs;
  508. sB = 1.0F - Bs;
  509. break;
  510. default:
  511. /* this should never happen */
  512. _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float");
  513. return;
  514. }
  515. /* Source Alpha factor */
  516. switch (ctx->Color.Blend[0].SrcA) {
  517. case GL_ZERO:
  518. sA = 0.0F;
  519. break;
  520. case GL_ONE:
  521. sA = 1.0F;
  522. break;
  523. case GL_DST_COLOR:
  524. sA = Ad;
  525. break;
  526. case GL_ONE_MINUS_DST_COLOR:
  527. sA = 1.0F - Ad;
  528. break;
  529. case GL_SRC_ALPHA:
  530. sA = As;
  531. break;
  532. case GL_ONE_MINUS_SRC_ALPHA:
  533. sA = 1.0F - As;
  534. break;
  535. case GL_DST_ALPHA:
  536. sA = Ad;
  537. break;
  538. case GL_ONE_MINUS_DST_ALPHA:
  539. sA = 1.0F - Ad;
  540. break;
  541. case GL_SRC_ALPHA_SATURATE:
  542. sA = 1.0;
  543. break;
  544. case GL_CONSTANT_COLOR:
  545. sA = ctx->Color.BlendColor[3];
  546. break;
  547. case GL_ONE_MINUS_CONSTANT_COLOR:
  548. sA = 1.0F - ctx->Color.BlendColor[3];
  549. break;
  550. case GL_CONSTANT_ALPHA:
  551. sA = ctx->Color.BlendColor[3];
  552. break;
  553. case GL_ONE_MINUS_CONSTANT_ALPHA:
  554. sA = 1.0F - ctx->Color.BlendColor[3];
  555. break;
  556. case GL_SRC_COLOR:
  557. sA = As;
  558. break;
  559. case GL_ONE_MINUS_SRC_COLOR:
  560. sA = 1.0F - As;
  561. break;
  562. default:
  563. /* this should never happen */
  564. sA = 0.0F;
  565. _mesa_problem(ctx, "Bad blend source A factor in blend_general_float");
  566. return;
  567. }
  568. /* Dest RGB factor */
  569. switch (ctx->Color.Blend[0].DstRGB) {
  570. case GL_ZERO:
  571. dR = dG = dB = 0.0F;
  572. break;
  573. case GL_ONE:
  574. dR = dG = dB = 1.0F;
  575. break;
  576. case GL_SRC_COLOR:
  577. dR = Rs;
  578. dG = Gs;
  579. dB = Bs;
  580. break;
  581. case GL_ONE_MINUS_SRC_COLOR:
  582. dR = 1.0F - Rs;
  583. dG = 1.0F - Gs;
  584. dB = 1.0F - Bs;
  585. break;
  586. case GL_SRC_ALPHA:
  587. dR = dG = dB = As;
  588. break;
  589. case GL_ONE_MINUS_SRC_ALPHA:
  590. dR = dG = dB = 1.0F - As;
  591. break;
  592. case GL_DST_ALPHA:
  593. dR = dG = dB = Ad;
  594. break;
  595. case GL_ONE_MINUS_DST_ALPHA:
  596. dR = dG = dB = 1.0F - Ad;
  597. break;
  598. case GL_CONSTANT_COLOR:
  599. dR = ctx->Color.BlendColor[0];
  600. dG = ctx->Color.BlendColor[1];
  601. dB = ctx->Color.BlendColor[2];
  602. break;
  603. case GL_ONE_MINUS_CONSTANT_COLOR:
  604. dR = 1.0F - ctx->Color.BlendColor[0];
  605. dG = 1.0F - ctx->Color.BlendColor[1];
  606. dB = 1.0F - ctx->Color.BlendColor[2];
  607. break;
  608. case GL_CONSTANT_ALPHA:
  609. dR = dG = dB = ctx->Color.BlendColor[3];
  610. break;
  611. case GL_ONE_MINUS_CONSTANT_ALPHA:
  612. dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
  613. break;
  614. case GL_DST_COLOR:
  615. dR = Rd;
  616. dG = Gd;
  617. dB = Bd;
  618. break;
  619. case GL_ONE_MINUS_DST_COLOR:
  620. dR = 1.0F - Rd;
  621. dG = 1.0F - Gd;
  622. dB = 1.0F - Bd;
  623. break;
  624. default:
  625. /* this should never happen */
  626. dR = dG = dB = 0.0F;
  627. _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float");
  628. return;
  629. }
  630. /* Dest Alpha factor */
  631. switch (ctx->Color.Blend[0].DstA) {
  632. case GL_ZERO:
  633. dA = 0.0F;
  634. break;
  635. case GL_ONE:
  636. dA = 1.0F;
  637. break;
  638. case GL_SRC_COLOR:
  639. dA = As;
  640. break;
  641. case GL_ONE_MINUS_SRC_COLOR:
  642. dA = 1.0F - As;
  643. break;
  644. case GL_SRC_ALPHA:
  645. dA = As;
  646. break;
  647. case GL_ONE_MINUS_SRC_ALPHA:
  648. dA = 1.0F - As;
  649. break;
  650. case GL_DST_ALPHA:
  651. dA = Ad;
  652. break;
  653. case GL_ONE_MINUS_DST_ALPHA:
  654. dA = 1.0F - Ad;
  655. break;
  656. case GL_CONSTANT_COLOR:
  657. dA = ctx->Color.BlendColor[3];
  658. break;
  659. case GL_ONE_MINUS_CONSTANT_COLOR:
  660. dA = 1.0F - ctx->Color.BlendColor[3];
  661. break;
  662. case GL_CONSTANT_ALPHA:
  663. dA = ctx->Color.BlendColor[3];
  664. break;
  665. case GL_ONE_MINUS_CONSTANT_ALPHA:
  666. dA = 1.0F - ctx->Color.BlendColor[3];
  667. break;
  668. case GL_DST_COLOR:
  669. dA = Ad;
  670. break;
  671. case GL_ONE_MINUS_DST_COLOR:
  672. dA = 1.0F - Ad;
  673. break;
  674. default:
  675. /* this should never happen */
  676. dA = 0.0F;
  677. _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float");
  678. return;
  679. }
  680. /* compute the blended RGB */
  681. switch (ctx->Color.Blend[0].EquationRGB) {
  682. case GL_FUNC_ADD:
  683. r = Rs * sR + Rd * dR;
  684. g = Gs * sG + Gd * dG;
  685. b = Bs * sB + Bd * dB;
  686. a = As * sA + Ad * dA;
  687. break;
  688. case GL_FUNC_SUBTRACT:
  689. r = Rs * sR - Rd * dR;
  690. g = Gs * sG - Gd * dG;
  691. b = Bs * sB - Bd * dB;
  692. a = As * sA - Ad * dA;
  693. break;
  694. case GL_FUNC_REVERSE_SUBTRACT:
  695. r = Rd * dR - Rs * sR;
  696. g = Gd * dG - Gs * sG;
  697. b = Bd * dB - Bs * sB;
  698. a = Ad * dA - As * sA;
  699. break;
  700. case GL_MIN:
  701. r = MIN2( Rd, Rs );
  702. g = MIN2( Gd, Gs );
  703. b = MIN2( Bd, Bs );
  704. break;
  705. case GL_MAX:
  706. r = MAX2( Rd, Rs );
  707. g = MAX2( Gd, Gs );
  708. b = MAX2( Bd, Bs );
  709. break;
  710. default:
  711. /* should never get here */
  712. r = g = b = 0.0F; /* silence uninitialized var warning */
  713. _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
  714. return;
  715. }
  716. /* compute the blended alpha */
  717. switch (ctx->Color.Blend[0].EquationA) {
  718. case GL_FUNC_ADD:
  719. a = As * sA + Ad * dA;
  720. break;
  721. case GL_FUNC_SUBTRACT:
  722. a = As * sA - Ad * dA;
  723. break;
  724. case GL_FUNC_REVERSE_SUBTRACT:
  725. a = Ad * dA - As * sA;
  726. break;
  727. case GL_MIN:
  728. a = MIN2( Ad, As );
  729. break;
  730. case GL_MAX:
  731. a = MAX2( Ad, As );
  732. break;
  733. default:
  734. /* should never get here */
  735. a = 0.0F; /* silence uninitialized var warning */
  736. _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
  737. return;
  738. }
  739. /* final clamping */
  740. #if 0
  741. rgba[i][RCOMP] = MAX2( r, 0.0F );
  742. rgba[i][GCOMP] = MAX2( g, 0.0F );
  743. rgba[i][BCOMP] = MAX2( b, 0.0F );
  744. rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F );
  745. #else
  746. ASSIGN_4V(rgba[i], r, g, b, a);
  747. #endif
  748. }
  749. }
  750. }
  751. /**
  752. * Do any blending operation, any chanType.
  753. */
  754. static void
  755. blend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[],
  756. void *src, const void *dst, GLenum chanType)
  757. {
  758. GLfloat (*rgbaF)[4], (*destF)[4];
  759. rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
  760. destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
  761. if (!rgbaF || !destF) {
  762. free(rgbaF);
  763. free(destF);
  764. _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending");
  765. return;
  766. }
  767. if (chanType == GL_UNSIGNED_BYTE) {
  768. GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
  769. const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
  770. GLuint i;
  771. /* convert ubytes to floats */
  772. for (i = 0; i < n; i++) {
  773. if (mask[i]) {
  774. rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]);
  775. rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]);
  776. rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]);
  777. rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]);
  778. destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]);
  779. destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]);
  780. destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]);
  781. destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]);
  782. }
  783. }
  784. /* do blend */
  785. blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
  786. /* convert back to ubytes */
  787. for (i = 0; i < n; i++) {
  788. if (mask[i])
  789. _mesa_unclamped_float_rgba_to_ubyte(rgba[i], rgbaF[i]);
  790. }
  791. }
  792. else if (chanType == GL_UNSIGNED_SHORT) {
  793. GLushort (*rgba)[4] = (GLushort (*)[4]) src;
  794. const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
  795. GLuint i;
  796. /* convert ushorts to floats */
  797. for (i = 0; i < n; i++) {
  798. if (mask[i]) {
  799. rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]);
  800. rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]);
  801. rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]);
  802. rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]);
  803. destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]);
  804. destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]);
  805. destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]);
  806. destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]);
  807. }
  808. }
  809. /* do blend */
  810. blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
  811. /* convert back to ushorts */
  812. for (i = 0; i < n; i++) {
  813. if (mask[i]) {
  814. UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]);
  815. UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]);
  816. UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]);
  817. UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]);
  818. }
  819. }
  820. }
  821. else {
  822. blend_general_float(ctx, n, mask, (GLfloat (*)[4]) src,
  823. (GLfloat (*)[4]) dst, chanType);
  824. }
  825. free(rgbaF);
  826. free(destF);
  827. }
  828. /**
  829. * Analyze current blending parameters to pick fastest blending function.
  830. * Result: the ctx->Color.BlendFunc pointer is updated.
  831. */
  832. void
  833. _swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType)
  834. {
  835. SWcontext *swrast = SWRAST_CONTEXT(ctx);
  836. const GLenum eq = ctx->Color.Blend[0].EquationRGB;
  837. const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
  838. const GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
  839. const GLenum srcA = ctx->Color.Blend[0].SrcA;
  840. const GLenum dstA = ctx->Color.Blend[0].DstA;
  841. if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) {
  842. swrast->BlendFunc = blend_general;
  843. }
  844. else if (eq == GL_MIN) {
  845. /* Note: GL_MIN ignores the blending weight factors */
  846. #if defined(USE_MMX_ASM)
  847. if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
  848. swrast->BlendFunc = _mesa_mmx_blend_min;
  849. }
  850. else
  851. #endif
  852. swrast->BlendFunc = blend_min;
  853. }
  854. else if (eq == GL_MAX) {
  855. /* Note: GL_MAX ignores the blending weight factors */
  856. #if defined(USE_MMX_ASM)
  857. if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
  858. swrast->BlendFunc = _mesa_mmx_blend_max;
  859. }
  860. else
  861. #endif
  862. swrast->BlendFunc = blend_max;
  863. }
  864. else if (srcRGB != srcA || dstRGB != dstA) {
  865. swrast->BlendFunc = blend_general;
  866. }
  867. else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA
  868. && dstRGB == GL_ONE_MINUS_SRC_ALPHA) {
  869. #if defined(USE_MMX_ASM)
  870. if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
  871. swrast->BlendFunc = _mesa_mmx_blend_transparency;
  872. }
  873. else
  874. #endif
  875. {
  876. if (chanType == GL_UNSIGNED_BYTE)
  877. swrast->BlendFunc = blend_transparency_ubyte;
  878. else if (chanType == GL_UNSIGNED_SHORT)
  879. swrast->BlendFunc = blend_transparency_ushort;
  880. else
  881. swrast->BlendFunc = blend_transparency_float;
  882. }
  883. }
  884. else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) {
  885. #if defined(USE_MMX_ASM)
  886. if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
  887. swrast->BlendFunc = _mesa_mmx_blend_add;
  888. }
  889. else
  890. #endif
  891. swrast->BlendFunc = blend_add;
  892. }
  893. else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT)
  894. && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR))
  895. ||
  896. ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT)
  897. && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) {
  898. #if defined(USE_MMX_ASM)
  899. if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
  900. swrast->BlendFunc = _mesa_mmx_blend_modulate;
  901. }
  902. else
  903. #endif
  904. swrast->BlendFunc = blend_modulate;
  905. }
  906. else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
  907. swrast->BlendFunc = blend_noop;
  908. }
  909. else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
  910. swrast->BlendFunc = blend_replace;
  911. }
  912. else {
  913. swrast->BlendFunc = blend_general;
  914. }
  915. }
  916. /**
  917. * Apply the blending operator to a span of pixels.
  918. * We can handle horizontal runs of pixels (spans) or arrays of x/y
  919. * pixel coordinates.
  920. */
  921. void
  922. _swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span)
  923. {
  924. SWcontext *swrast = SWRAST_CONTEXT(ctx);
  925. void *rbPixels;
  926. ASSERT(span->end <= SWRAST_MAX_WIDTH);
  927. ASSERT(span->arrayMask & SPAN_RGBA);
  928. ASSERT(!ctx->Color.ColorLogicOpEnabled);
  929. rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
  930. swrast->BlendFunc(ctx, span->end, span->array->mask,
  931. span->array->rgba, rbPixels, span->array->ChanType);
  932. }