Path: blob/21.2-virgl/src/gallium/drivers/softpipe/sp_quad_blend.c
4570 views
/**************************************************************************1*2* Copyright 2007 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/**28* quad blending29* \author Brian Paul30*/3132#include "pipe/p_defines.h"33#include "util/u_math.h"34#include "util/u_memory.h"35#include "util/format/u_format.h"36#include "util/u_dual_blend.h"37#include "sp_context.h"38#include "sp_state.h"39#include "sp_quad.h"40#include "sp_tile_cache.h"41#include "sp_quad_pipe.h"424344enum format45{46RGBA,47RGB,48LUMINANCE,49LUMINANCE_ALPHA,50INTENSITY51};525354/** Subclass of quad_stage */55struct blend_quad_stage56{57struct quad_stage base;58boolean clamp[PIPE_MAX_COLOR_BUFS]; /**< clamp colors to [0,1]? */59enum format base_format[PIPE_MAX_COLOR_BUFS];60enum util_format_type format_type[PIPE_MAX_COLOR_BUFS];61};626364/** cast wrapper */65static inline struct blend_quad_stage *66blend_quad_stage(struct quad_stage *stage)67{68return (struct blend_quad_stage *) stage;69}707172#define VEC4_COPY(DST, SRC) \73do { \74DST[0] = SRC[0]; \75DST[1] = SRC[1]; \76DST[2] = SRC[2]; \77DST[3] = SRC[3]; \78} while(0)7980#define VEC4_SCALAR(DST, SRC) \81do { \82DST[0] = SRC; \83DST[1] = SRC; \84DST[2] = SRC; \85DST[3] = SRC; \86} while(0)8788#define VEC4_ADD(R, A, B) \89do { \90R[0] = A[0] + B[0]; \91R[1] = A[1] + B[1]; \92R[2] = A[2] + B[2]; \93R[3] = A[3] + B[3]; \94} while (0)9596#define VEC4_SUB(R, A, B) \97do { \98R[0] = A[0] - B[0]; \99R[1] = A[1] - B[1]; \100R[2] = A[2] - B[2]; \101R[3] = A[3] - B[3]; \102} while (0)103104/** Add and limit result to ceiling of 1.0 */105#define VEC4_ADD_SAT(R, A, B) \106do { \107R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \108R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \109R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \110R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \111} while (0)112113/** Subtract and limit result to floor of 0.0 */114#define VEC4_SUB_SAT(R, A, B) \115do { \116R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \117R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \118R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \119R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \120} while (0)121122#define VEC4_MUL(R, A, B) \123do { \124R[0] = A[0] * B[0]; \125R[1] = A[1] * B[1]; \126R[2] = A[2] * B[2]; \127R[3] = A[3] * B[3]; \128} while (0)129130#define VEC4_MIN(R, A, B) \131do { \132R[0] = (A[0] < B[0]) ? A[0] : B[0]; \133R[1] = (A[1] < B[1]) ? A[1] : B[1]; \134R[2] = (A[2] < B[2]) ? A[2] : B[2]; \135R[3] = (A[3] < B[3]) ? A[3] : B[3]; \136} while (0)137138#define VEC4_MAX(R, A, B) \139do { \140R[0] = (A[0] > B[0]) ? A[0] : B[0]; \141R[1] = (A[1] > B[1]) ? A[1] : B[1]; \142R[2] = (A[2] > B[2]) ? A[2] : B[2]; \143R[3] = (A[3] > B[3]) ? A[3] : B[3]; \144} while (0)145146147148static void149logicop_quad(struct quad_stage *qs,150float (*quadColor)[4],151float (*dest)[4])152{153struct softpipe_context *softpipe = qs->softpipe;154ubyte src[4][4], dst[4][4], res[4][4];155uint *src4 = (uint *) src;156uint *dst4 = (uint *) dst;157uint *res4 = (uint *) res;158uint j;159160161/* convert to ubyte */162for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */163dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */164dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */165dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */166dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */167168src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */169src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */170src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */171src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */172173res[j][0] = 0;174}175176switch (softpipe->blend->logicop_func) {177case PIPE_LOGICOP_CLEAR:178for (j = 0; j < 4; j++)179res4[j] = 0;180break;181case PIPE_LOGICOP_NOR:182for (j = 0; j < 4; j++)183res4[j] = ~(src4[j] | dst4[j]);184break;185case PIPE_LOGICOP_AND_INVERTED:186for (j = 0; j < 4; j++)187res4[j] = ~src4[j] & dst4[j];188break;189case PIPE_LOGICOP_COPY_INVERTED:190for (j = 0; j < 4; j++)191res4[j] = ~src4[j];192break;193case PIPE_LOGICOP_AND_REVERSE:194for (j = 0; j < 4; j++)195res4[j] = src4[j] & ~dst4[j];196break;197case PIPE_LOGICOP_INVERT:198for (j = 0; j < 4; j++)199res4[j] = ~dst4[j];200break;201case PIPE_LOGICOP_XOR:202for (j = 0; j < 4; j++)203res4[j] = dst4[j] ^ src4[j];204break;205case PIPE_LOGICOP_NAND:206for (j = 0; j < 4; j++)207res4[j] = ~(src4[j] & dst4[j]);208break;209case PIPE_LOGICOP_AND:210for (j = 0; j < 4; j++)211res4[j] = src4[j] & dst4[j];212break;213case PIPE_LOGICOP_EQUIV:214for (j = 0; j < 4; j++)215res4[j] = ~(src4[j] ^ dst4[j]);216break;217case PIPE_LOGICOP_NOOP:218for (j = 0; j < 4; j++)219res4[j] = dst4[j];220break;221case PIPE_LOGICOP_OR_INVERTED:222for (j = 0; j < 4; j++)223res4[j] = ~src4[j] | dst4[j];224break;225case PIPE_LOGICOP_COPY:226for (j = 0; j < 4; j++)227res4[j] = src4[j];228break;229case PIPE_LOGICOP_OR_REVERSE:230for (j = 0; j < 4; j++)231res4[j] = src4[j] | ~dst4[j];232break;233case PIPE_LOGICOP_OR:234for (j = 0; j < 4; j++)235res4[j] = src4[j] | dst4[j];236break;237case PIPE_LOGICOP_SET:238for (j = 0; j < 4; j++)239res4[j] = ~0;240break;241default:242assert(0 && "invalid logicop mode");243}244245for (j = 0; j < 4; j++) {246quadColor[j][0] = ubyte_to_float(res[j][0]);247quadColor[j][1] = ubyte_to_float(res[j][1]);248quadColor[j][2] = ubyte_to_float(res[j][2]);249quadColor[j][3] = ubyte_to_float(res[j][3]);250}251}252253254255/**256* Do blending for a 2x2 quad for one color buffer.257* \param quadColor the incoming quad colors258* \param dest the destination/framebuffer quad colors259* \param const_blend_color the constant blend color260* \param blend_index which set of blending terms to use261*/262static void263blend_quad(struct quad_stage *qs,264float (*quadColor)[4],265float (*quadColor2)[4],266float (*dest)[4],267const float const_blend_color[4],268unsigned blend_index)269{270static const float zero[4] = { 0, 0, 0, 0 };271static const float one[4] = { 1, 1, 1, 1 };272struct softpipe_context *softpipe = qs->softpipe;273float source[4][TGSI_QUAD_SIZE] = { { 0 } };274float blend_dest[4][TGSI_QUAD_SIZE];275276/*277* Compute src/first term RGB278*/279switch (softpipe->blend->rt[blend_index].rgb_src_factor) {280case PIPE_BLENDFACTOR_ONE:281VEC4_COPY(source[0], quadColor[0]); /* R */282VEC4_COPY(source[1], quadColor[1]); /* G */283VEC4_COPY(source[2], quadColor[2]); /* B */284break;285case PIPE_BLENDFACTOR_SRC_COLOR:286VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */287VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */288VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */289break;290case PIPE_BLENDFACTOR_SRC_ALPHA:291{292const float *alpha = quadColor[3];293VEC4_MUL(source[0], quadColor[0], alpha); /* R */294VEC4_MUL(source[1], quadColor[1], alpha); /* G */295VEC4_MUL(source[2], quadColor[2], alpha); /* B */296}297break;298case PIPE_BLENDFACTOR_DST_COLOR:299VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */300VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */301VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */302break;303case PIPE_BLENDFACTOR_DST_ALPHA:304{305const float *alpha = dest[3];306VEC4_MUL(source[0], quadColor[0], alpha); /* R */307VEC4_MUL(source[1], quadColor[1], alpha); /* G */308VEC4_MUL(source[2], quadColor[2], alpha); /* B */309}310break;311case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:312{313const float *alpha = quadColor[3];314float diff[4], temp[4];315VEC4_SUB(diff, one, dest[3]);316VEC4_MIN(temp, alpha, diff);317VEC4_MUL(source[0], quadColor[0], temp); /* R */318VEC4_MUL(source[1], quadColor[1], temp); /* G */319VEC4_MUL(source[2], quadColor[2], temp); /* B */320}321break;322case PIPE_BLENDFACTOR_CONST_COLOR:323{324float comp[4];325VEC4_SCALAR(comp, const_blend_color[0]); /* R */326VEC4_MUL(source[0], quadColor[0], comp); /* R */327VEC4_SCALAR(comp, const_blend_color[1]); /* G */328VEC4_MUL(source[1], quadColor[1], comp); /* G */329VEC4_SCALAR(comp, const_blend_color[2]); /* B */330VEC4_MUL(source[2], quadColor[2], comp); /* B */331}332break;333case PIPE_BLENDFACTOR_CONST_ALPHA:334{335float alpha[4];336VEC4_SCALAR(alpha, const_blend_color[3]);337VEC4_MUL(source[0], quadColor[0], alpha); /* R */338VEC4_MUL(source[1], quadColor[1], alpha); /* G */339VEC4_MUL(source[2], quadColor[2], alpha); /* B */340}341break;342case PIPE_BLENDFACTOR_SRC1_COLOR:343VEC4_MUL(source[0], quadColor[0], quadColor2[0]); /* R */344VEC4_MUL(source[1], quadColor[1], quadColor2[1]); /* G */345VEC4_MUL(source[2], quadColor[2], quadColor2[2]); /* B */346break;347case PIPE_BLENDFACTOR_SRC1_ALPHA:348{349const float *alpha = quadColor2[3];350VEC4_MUL(source[0], quadColor[0], alpha); /* R */351VEC4_MUL(source[1], quadColor[1], alpha); /* G */352VEC4_MUL(source[2], quadColor[2], alpha); /* B */353}354break;355case PIPE_BLENDFACTOR_ZERO:356VEC4_COPY(source[0], zero); /* R */357VEC4_COPY(source[1], zero); /* G */358VEC4_COPY(source[2], zero); /* B */359break;360case PIPE_BLENDFACTOR_INV_SRC_COLOR:361{362float inv_comp[4];363VEC4_SUB(inv_comp, one, quadColor[0]); /* R */364VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */365VEC4_SUB(inv_comp, one, quadColor[1]); /* G */366VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */367VEC4_SUB(inv_comp, one, quadColor[2]); /* B */368VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */369}370break;371case PIPE_BLENDFACTOR_INV_SRC_ALPHA:372{373float inv_alpha[4];374VEC4_SUB(inv_alpha, one, quadColor[3]);375VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */376VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */377VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */378}379break;380case PIPE_BLENDFACTOR_INV_DST_ALPHA:381{382float inv_alpha[4];383VEC4_SUB(inv_alpha, one, dest[3]);384VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */385VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */386VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */387}388break;389case PIPE_BLENDFACTOR_INV_DST_COLOR:390{391float inv_comp[4];392VEC4_SUB(inv_comp, one, dest[0]); /* R */393VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */394VEC4_SUB(inv_comp, one, dest[1]); /* G */395VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */396VEC4_SUB(inv_comp, one, dest[2]); /* B */397VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */398}399break;400case PIPE_BLENDFACTOR_INV_CONST_COLOR:401{402float inv_comp[4];403/* R */404VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]);405VEC4_MUL(source[0], quadColor[0], inv_comp);406/* G */407VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]);408VEC4_MUL(source[1], quadColor[1], inv_comp);409/* B */410VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]);411VEC4_MUL(source[2], quadColor[2], inv_comp);412}413break;414case PIPE_BLENDFACTOR_INV_CONST_ALPHA:415{416float inv_alpha[4];417VEC4_SCALAR(inv_alpha, 1.0f - const_blend_color[3]);418VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */419VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */420VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */421}422break;423case PIPE_BLENDFACTOR_INV_SRC1_COLOR:424{425float inv_comp[4];426VEC4_SUB(inv_comp, one, quadColor2[0]); /* R */427VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */428VEC4_SUB(inv_comp, one, quadColor2[1]); /* G */429VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */430VEC4_SUB(inv_comp, one, quadColor2[2]); /* B */431VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */432}433break;434case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:435{436float inv_alpha[4];437VEC4_SUB(inv_alpha, one, quadColor2[3]);438VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */439VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */440VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */441}442break;443default:444assert(0 && "invalid rgb src factor");445}446447/*448* Compute src/first term A449*/450switch (softpipe->blend->rt[blend_index].alpha_src_factor) {451case PIPE_BLENDFACTOR_ONE:452VEC4_COPY(source[3], quadColor[3]); /* A */453break;454case PIPE_BLENDFACTOR_SRC_COLOR:455FALLTHROUGH;456case PIPE_BLENDFACTOR_SRC_ALPHA:457{458const float *alpha = quadColor[3];459VEC4_MUL(source[3], quadColor[3], alpha); /* A */460}461break;462case PIPE_BLENDFACTOR_DST_COLOR:463FALLTHROUGH;464case PIPE_BLENDFACTOR_DST_ALPHA:465VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */466break;467case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:468/* multiply alpha by 1.0 */469VEC4_COPY(source[3], quadColor[3]); /* A */470break;471case PIPE_BLENDFACTOR_CONST_COLOR:472FALLTHROUGH;473case PIPE_BLENDFACTOR_CONST_ALPHA:474{475float comp[4];476VEC4_SCALAR(comp, const_blend_color[3]); /* A */477VEC4_MUL(source[3], quadColor[3], comp); /* A */478}479break;480case PIPE_BLENDFACTOR_ZERO:481VEC4_COPY(source[3], zero); /* A */482break;483case PIPE_BLENDFACTOR_INV_SRC_COLOR:484FALLTHROUGH;485case PIPE_BLENDFACTOR_INV_SRC_ALPHA:486{487float inv_alpha[4];488VEC4_SUB(inv_alpha, one, quadColor[3]);489VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */490}491break;492case PIPE_BLENDFACTOR_INV_DST_COLOR:493FALLTHROUGH;494case PIPE_BLENDFACTOR_INV_DST_ALPHA:495{496float inv_alpha[4];497VEC4_SUB(inv_alpha, one, dest[3]);498VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */499}500break;501case PIPE_BLENDFACTOR_INV_CONST_COLOR:502FALLTHROUGH;503case PIPE_BLENDFACTOR_INV_CONST_ALPHA:504{505float inv_comp[4];506/* A */507VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);508VEC4_MUL(source[3], quadColor[3], inv_comp);509}510break;511case PIPE_BLENDFACTOR_SRC1_COLOR:512FALLTHROUGH;513case PIPE_BLENDFACTOR_SRC1_ALPHA:514{515const float *alpha = quadColor2[3];516VEC4_MUL(source[3], quadColor[3], alpha); /* A */517}518break;519case PIPE_BLENDFACTOR_INV_SRC1_COLOR:520FALLTHROUGH;521case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:522{523float inv_alpha[4];524VEC4_SUB(inv_alpha, one, quadColor2[3]);525VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */526}527break;528default:529assert(0 && "invalid alpha src factor");530}531532/* Save the original dest for use in masking */533VEC4_COPY(blend_dest[0], dest[0]);534VEC4_COPY(blend_dest[1], dest[1]);535VEC4_COPY(blend_dest[2], dest[2]);536VEC4_COPY(blend_dest[3], dest[3]);537538539/*540* Compute blend_dest/second term RGB541*/542switch (softpipe->blend->rt[blend_index].rgb_dst_factor) {543case PIPE_BLENDFACTOR_ONE:544/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */545break;546case PIPE_BLENDFACTOR_SRC_COLOR:547VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[0]); /* R */548VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[1]); /* G */549VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[2]); /* B */550break;551case PIPE_BLENDFACTOR_SRC_ALPHA:552VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[3]); /* R * A */553VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[3]); /* G * A */554VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[3]); /* B * A */555break;556case PIPE_BLENDFACTOR_DST_ALPHA:557VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[3]); /* R * A */558VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[3]); /* G * A */559VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[3]); /* B * A */560break;561case PIPE_BLENDFACTOR_DST_COLOR:562VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[0]); /* R */563VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[1]); /* G */564VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[2]); /* B */565break;566case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:567{568const float *alpha = quadColor[3];569float diff[4], temp[4];570VEC4_SUB(diff, one, blend_dest[3]);571VEC4_MIN(temp, alpha, diff);572VEC4_MUL(blend_dest[0], blend_dest[0], temp); /* R */573VEC4_MUL(blend_dest[1], blend_dest[1], temp); /* G */574VEC4_MUL(blend_dest[2], blend_dest[2], temp); /* B */575}576break;577case PIPE_BLENDFACTOR_CONST_COLOR:578{579float comp[4];580VEC4_SCALAR(comp, const_blend_color[0]); /* R */581VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */582VEC4_SCALAR(comp, const_blend_color[1]); /* G */583VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */584VEC4_SCALAR(comp, const_blend_color[2]); /* B */585VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */586}587break;588case PIPE_BLENDFACTOR_CONST_ALPHA:589{590float comp[4];591VEC4_SCALAR(comp, const_blend_color[3]); /* A */592VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */593VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */594VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */595}596break;597case PIPE_BLENDFACTOR_ZERO:598VEC4_COPY(blend_dest[0], zero); /* R */599VEC4_COPY(blend_dest[1], zero); /* G */600VEC4_COPY(blend_dest[2], zero); /* B */601break;602case PIPE_BLENDFACTOR_SRC1_COLOR:603VEC4_MUL(blend_dest[0], blend_dest[0], quadColor2[0]); /* R */604VEC4_MUL(blend_dest[1], blend_dest[1], quadColor2[1]); /* G */605VEC4_MUL(blend_dest[2], blend_dest[2], quadColor2[2]); /* B */606break;607case PIPE_BLENDFACTOR_SRC1_ALPHA:608VEC4_MUL(blend_dest[0], blend_dest[0], quadColor2[3]); /* R * A */609VEC4_MUL(blend_dest[1], blend_dest[1], quadColor2[3]); /* G * A */610VEC4_MUL(blend_dest[2], blend_dest[2], quadColor2[3]); /* B * A */611break;612case PIPE_BLENDFACTOR_INV_SRC_COLOR:613{614float inv_comp[4];615VEC4_SUB(inv_comp, one, quadColor[0]); /* R */616VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */617VEC4_SUB(inv_comp, one, quadColor[1]); /* G */618VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */619VEC4_SUB(inv_comp, one, quadColor[2]); /* B */620VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */621}622break;623case PIPE_BLENDFACTOR_INV_SRC_ALPHA:624{625float one_minus_alpha[TGSI_QUAD_SIZE];626VEC4_SUB(one_minus_alpha, one, quadColor[3]);627VEC4_MUL(blend_dest[0], blend_dest[0], one_minus_alpha); /* R */628VEC4_MUL(blend_dest[1], blend_dest[1], one_minus_alpha); /* G */629VEC4_MUL(blend_dest[2], blend_dest[2], one_minus_alpha); /* B */630}631break;632case PIPE_BLENDFACTOR_INV_DST_ALPHA:633{634float inv_comp[4];635VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */636VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */637VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */638VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */639}640break;641case PIPE_BLENDFACTOR_INV_DST_COLOR:642{643float inv_comp[4];644VEC4_SUB(inv_comp, one, blend_dest[0]); /* R */645VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp); /* R */646VEC4_SUB(inv_comp, one, blend_dest[1]); /* G */647VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp); /* G */648VEC4_SUB(inv_comp, one, blend_dest[2]); /* B */649VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp); /* B */650}651break;652case PIPE_BLENDFACTOR_INV_CONST_COLOR:653{654float inv_comp[4];655/* R */656VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]);657VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp);658/* G */659VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]);660VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp);661/* B */662VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]);663VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp);664}665break;666case PIPE_BLENDFACTOR_INV_CONST_ALPHA:667{668float inv_comp[4];669VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);670VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp);671VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp);672VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp);673}674break;675case PIPE_BLENDFACTOR_INV_SRC1_COLOR:676{677float inv_comp[4];678VEC4_SUB(inv_comp, one, quadColor2[0]); /* R */679VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */680VEC4_SUB(inv_comp, one, quadColor2[1]); /* G */681VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */682VEC4_SUB(inv_comp, one, quadColor2[2]); /* B */683VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */684}685break;686case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:687{688float one_minus_alpha[TGSI_QUAD_SIZE];689VEC4_SUB(one_minus_alpha, one, quadColor2[3]);690VEC4_MUL(blend_dest[0], blend_dest[0], one_minus_alpha); /* R */691VEC4_MUL(blend_dest[1], blend_dest[1], one_minus_alpha); /* G */692VEC4_MUL(blend_dest[2], blend_dest[2], one_minus_alpha); /* B */693}694break;695default:696assert(0 && "invalid rgb dst factor");697}698699/*700* Compute blend_dest/second term A701*/702switch (softpipe->blend->rt[blend_index].alpha_dst_factor) {703case PIPE_BLENDFACTOR_ONE:704/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */705break;706case PIPE_BLENDFACTOR_SRC_COLOR:707FALLTHROUGH;708case PIPE_BLENDFACTOR_SRC_ALPHA:709VEC4_MUL(blend_dest[3], blend_dest[3], quadColor[3]); /* A * A */710break;711case PIPE_BLENDFACTOR_DST_COLOR:712FALLTHROUGH;713case PIPE_BLENDFACTOR_DST_ALPHA:714VEC4_MUL(blend_dest[3], blend_dest[3], blend_dest[3]); /* A */715break;716case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:717/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */718break;719case PIPE_BLENDFACTOR_CONST_COLOR:720FALLTHROUGH;721case PIPE_BLENDFACTOR_CONST_ALPHA:722{723float comp[4];724VEC4_SCALAR(comp, const_blend_color[3]); /* A */725VEC4_MUL(blend_dest[3], blend_dest[3], comp); /* A */726}727break;728case PIPE_BLENDFACTOR_ZERO:729VEC4_COPY(blend_dest[3], zero); /* A */730break;731case PIPE_BLENDFACTOR_INV_SRC_COLOR:732FALLTHROUGH;733case PIPE_BLENDFACTOR_INV_SRC_ALPHA:734{735float one_minus_alpha[TGSI_QUAD_SIZE];736VEC4_SUB(one_minus_alpha, one, quadColor[3]);737VEC4_MUL(blend_dest[3], blend_dest[3], one_minus_alpha); /* A */738}739break;740case PIPE_BLENDFACTOR_INV_DST_COLOR:741FALLTHROUGH;742case PIPE_BLENDFACTOR_INV_DST_ALPHA:743{744float inv_comp[4];745VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */746VEC4_MUL(blend_dest[3], inv_comp, blend_dest[3]); /* A */747}748break;749case PIPE_BLENDFACTOR_INV_CONST_COLOR:750FALLTHROUGH;751case PIPE_BLENDFACTOR_INV_CONST_ALPHA:752{753float inv_comp[4];754VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);755VEC4_MUL(blend_dest[3], blend_dest[3], inv_comp);756}757break;758case PIPE_BLENDFACTOR_SRC1_COLOR:759FALLTHROUGH;760case PIPE_BLENDFACTOR_SRC1_ALPHA:761VEC4_MUL(blend_dest[3], blend_dest[3], quadColor2[3]); /* A * A */762break;763case PIPE_BLENDFACTOR_INV_SRC1_COLOR:764FALLTHROUGH;765case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:766{767float one_minus_alpha[TGSI_QUAD_SIZE];768VEC4_SUB(one_minus_alpha, one, quadColor2[3]);769VEC4_MUL(blend_dest[3], blend_dest[3], one_minus_alpha); /* A */770}771break;772default:773assert(0 && "invalid alpha dst factor");774}775776/*777* Combine RGB terms778*/779switch (softpipe->blend->rt[blend_index].rgb_func) {780case PIPE_BLEND_ADD:781VEC4_ADD(quadColor[0], source[0], blend_dest[0]); /* R */782VEC4_ADD(quadColor[1], source[1], blend_dest[1]); /* G */783VEC4_ADD(quadColor[2], source[2], blend_dest[2]); /* B */784break;785case PIPE_BLEND_SUBTRACT:786VEC4_SUB(quadColor[0], source[0], blend_dest[0]); /* R */787VEC4_SUB(quadColor[1], source[1], blend_dest[1]); /* G */788VEC4_SUB(quadColor[2], source[2], blend_dest[2]); /* B */789break;790case PIPE_BLEND_REVERSE_SUBTRACT:791VEC4_SUB(quadColor[0], blend_dest[0], source[0]); /* R */792VEC4_SUB(quadColor[1], blend_dest[1], source[1]); /* G */793VEC4_SUB(quadColor[2], blend_dest[2], source[2]); /* B */794break;795case PIPE_BLEND_MIN:796VEC4_MIN(quadColor[0], source[0], blend_dest[0]); /* R */797VEC4_MIN(quadColor[1], source[1], blend_dest[1]); /* G */798VEC4_MIN(quadColor[2], source[2], blend_dest[2]); /* B */799break;800case PIPE_BLEND_MAX:801VEC4_MAX(quadColor[0], source[0], blend_dest[0]); /* R */802VEC4_MAX(quadColor[1], source[1], blend_dest[1]); /* G */803VEC4_MAX(quadColor[2], source[2], blend_dest[2]); /* B */804break;805default:806assert(0 && "invalid rgb blend func");807}808809/*810* Combine A terms811*/812switch (softpipe->blend->rt[blend_index].alpha_func) {813case PIPE_BLEND_ADD:814VEC4_ADD(quadColor[3], source[3], blend_dest[3]); /* A */815break;816case PIPE_BLEND_SUBTRACT:817VEC4_SUB(quadColor[3], source[3], blend_dest[3]); /* A */818break;819case PIPE_BLEND_REVERSE_SUBTRACT:820VEC4_SUB(quadColor[3], blend_dest[3], source[3]); /* A */821break;822case PIPE_BLEND_MIN:823VEC4_MIN(quadColor[3], source[3], blend_dest[3]); /* A */824break;825case PIPE_BLEND_MAX:826VEC4_MAX(quadColor[3], source[3], blend_dest[3]); /* A */827break;828default:829assert(0 && "invalid alpha blend func");830}831}832833static void834colormask_quad(unsigned colormask,835float (*quadColor)[4],836float (*dest)[4])837{838/* R */839if (!(colormask & PIPE_MASK_R))840COPY_4V(quadColor[0], dest[0]);841842/* G */843if (!(colormask & PIPE_MASK_G))844COPY_4V(quadColor[1], dest[1]);845846/* B */847if (!(colormask & PIPE_MASK_B))848COPY_4V(quadColor[2], dest[2]);849850/* A */851if (!(colormask & PIPE_MASK_A))852COPY_4V(quadColor[3], dest[3]);853}854855856/**857* Clamp all colors in a quad to [0, 1]858*/859static void860clamp_colors(float (*quadColor)[4])861{862unsigned i, j;863864for (i = 0; i < 4; i++) {865for (j = 0; j < TGSI_QUAD_SIZE; j++) {866quadColor[i][j] = CLAMP(quadColor[i][j], 0.0F, 1.0F);867}868}869}870871872/**873* If we're drawing to a luminance, luminance/alpha or intensity surface874* we have to adjust (rebase) the fragment/quad colors before writing them875* to the tile cache. The tile cache always stores RGBA colors but if876* we're caching a L/A surface (for example) we need to be sure that R=G=B877* so that subsequent reads from the surface cache appear to return L/A878* values.879* The piglit fbo-blending-formats test will exercise this.880*/881static void882rebase_colors(enum format base_format, float (*quadColor)[4])883{884unsigned i;885886switch (base_format) {887case RGB:888for (i = 0; i < 4; i++) {889/* A = 1 */890quadColor[3][i] = 1.0F;891}892break;893case LUMINANCE:894for (i = 0; i < 4; i++) {895/* B = G = R */896quadColor[2][i] = quadColor[1][i] = quadColor[0][i];897/* A = 1 */898quadColor[3][i] = 1.0F;899}900break;901case LUMINANCE_ALPHA:902for (i = 0; i < 4; i++) {903/* B = G = R */904quadColor[2][i] = quadColor[1][i] = quadColor[0][i];905}906break;907case INTENSITY:908for (i = 0; i < 4; i++) {909/* A = B = G = R */910quadColor[3][i] = quadColor[2][i] = quadColor[1][i] = quadColor[0][i];911}912break;913default:914; /* nothing */915}916}917918static void919blend_fallback(struct quad_stage *qs,920struct quad_header *quads[],921unsigned nr)922{923const struct blend_quad_stage *bqs = blend_quad_stage(qs);924struct softpipe_context *softpipe = qs->softpipe;925const struct pipe_blend_state *blend = softpipe->blend;926unsigned cbuf;927boolean write_all =928softpipe->fs_variant->info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS];929930for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {931if (softpipe->framebuffer.cbufs[cbuf]) {932/* which blend/mask state index to use: */933const uint blend_buf = blend->independent_blend_enable ? cbuf : 0;934float dest[4][TGSI_QUAD_SIZE];935struct softpipe_cached_tile *tile936= sp_get_cached_tile(softpipe->cbuf_cache[cbuf],937quads[0]->input.x0,938quads[0]->input.y0, quads[0]->input.layer);939const boolean clamp = bqs->clamp[cbuf];940const float *blend_color;941const boolean dual_source_blend = util_blend_state_is_dual(blend, cbuf);942uint q, i, j;943944if (clamp)945blend_color = softpipe->blend_color_clamped.color;946else947blend_color = softpipe->blend_color.color;948949for (q = 0; q < nr; q++) {950struct quad_header *quad = quads[q];951float (*quadColor)[4];952float (*quadColor2)[4] = NULL;953float temp_quad_color[TGSI_QUAD_SIZE][4];954const int itx = (quad->input.x0 & (TILE_SIZE-1));955const int ity = (quad->input.y0 & (TILE_SIZE-1));956957if (write_all) {958for (j = 0; j < TGSI_QUAD_SIZE; j++) {959for (i = 0; i < 4; i++) {960temp_quad_color[i][j] = quad->output.color[0][i][j];961}962}963quadColor = temp_quad_color;964} else {965quadColor = quad->output.color[cbuf];966if (dual_source_blend)967quadColor2 = quad->output.color[cbuf + 1];968}969970/* If fixed-point dest color buffer, need to clamp the incoming971* fragment colors now.972*/973if (clamp || softpipe->rasterizer->clamp_fragment_color) {974clamp_colors(quadColor);975}976977/* get/swizzle dest colors978*/979for (j = 0; j < TGSI_QUAD_SIZE; j++) {980int x = itx + (j & 1);981int y = ity + (j >> 1);982for (i = 0; i < 4; i++) {983dest[i][j] = tile->data.color[y][x][i];984}985}986987988if (blend->logicop_enable) {989if (bqs->format_type[cbuf] != UTIL_FORMAT_TYPE_FLOAT) {990logicop_quad( qs, quadColor, dest );991}992}993else if (blend->rt[blend_buf].blend_enable) {994blend_quad(qs, quadColor, quadColor2, dest, blend_color, blend_buf);995996/* If fixed-point dest color buffer, need to clamp the outgoing997* fragment colors now.998*/999if (clamp) {1000clamp_colors(quadColor);1001}1002}10031004rebase_colors(bqs->base_format[cbuf], quadColor);10051006if (blend->rt[blend_buf].colormask != 0xf)1007colormask_quad( blend->rt[cbuf].colormask, quadColor, dest);10081009/* Output color values1010*/1011for (j = 0; j < TGSI_QUAD_SIZE; j++) {1012if (quad->inout.mask & (1 << j)) {1013int x = itx + (j & 1);1014int y = ity + (j >> 1);1015for (i = 0; i < 4; i++) { /* loop over color chans */1016tile->data.color[y][x][i] = quadColor[i][j];1017}1018}1019}1020}1021}1022}1023}102410251026static void1027blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs,1028struct quad_header *quads[],1029unsigned nr)1030{1031const struct blend_quad_stage *bqs = blend_quad_stage(qs);1032static const float one[4] = { 1, 1, 1, 1 };1033float one_minus_alpha[TGSI_QUAD_SIZE];1034float dest[4][TGSI_QUAD_SIZE];1035float source[4][TGSI_QUAD_SIZE];1036uint i, j, q;10371038struct softpipe_cached_tile *tile1039= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],1040quads[0]->input.x0,1041quads[0]->input.y0, quads[0]->input.layer);10421043for (q = 0; q < nr; q++) {1044struct quad_header *quad = quads[q];1045float (*quadColor)[4] = quad->output.color[0];1046const float *alpha = quadColor[3];1047const int itx = (quad->input.x0 & (TILE_SIZE-1));1048const int ity = (quad->input.y0 & (TILE_SIZE-1));10491050/* get/swizzle dest colors */1051for (j = 0; j < TGSI_QUAD_SIZE; j++) {1052int x = itx + (j & 1);1053int y = ity + (j >> 1);1054for (i = 0; i < 4; i++) {1055dest[i][j] = tile->data.color[y][x][i];1056}1057}10581059/* If fixed-point dest color buffer, need to clamp the incoming1060* fragment colors now.1061*/1062if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) {1063clamp_colors(quadColor);1064}10651066VEC4_MUL(source[0], quadColor[0], alpha); /* R */1067VEC4_MUL(source[1], quadColor[1], alpha); /* G */1068VEC4_MUL(source[2], quadColor[2], alpha); /* B */1069VEC4_MUL(source[3], quadColor[3], alpha); /* A */10701071VEC4_SUB(one_minus_alpha, one, alpha);1072VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */1073VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */1074VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */1075VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */10761077VEC4_ADD(quadColor[0], source[0], dest[0]); /* R */1078VEC4_ADD(quadColor[1], source[1], dest[1]); /* G */1079VEC4_ADD(quadColor[2], source[2], dest[2]); /* B */1080VEC4_ADD(quadColor[3], source[3], dest[3]); /* A */10811082/* If fixed-point dest color buffer, need to clamp the outgoing1083* fragment colors now.1084*/1085if (bqs->clamp[0]) {1086clamp_colors(quadColor);1087}10881089rebase_colors(bqs->base_format[0], quadColor);10901091for (j = 0; j < TGSI_QUAD_SIZE; j++) {1092if (quad->inout.mask & (1 << j)) {1093int x = itx + (j & 1);1094int y = ity + (j >> 1);1095for (i = 0; i < 4; i++) { /* loop over color chans */1096tile->data.color[y][x][i] = quadColor[i][j];1097}1098}1099}1100}1101}11021103static void1104blend_single_add_one_one(struct quad_stage *qs,1105struct quad_header *quads[],1106unsigned nr)1107{1108const struct blend_quad_stage *bqs = blend_quad_stage(qs);1109float dest[4][TGSI_QUAD_SIZE];1110uint i, j, q;11111112struct softpipe_cached_tile *tile1113= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],1114quads[0]->input.x0,1115quads[0]->input.y0, quads[0]->input.layer);11161117for (q = 0; q < nr; q++) {1118struct quad_header *quad = quads[q];1119float (*quadColor)[4] = quad->output.color[0];1120const int itx = (quad->input.x0 & (TILE_SIZE-1));1121const int ity = (quad->input.y0 & (TILE_SIZE-1));11221123/* get/swizzle dest colors */1124for (j = 0; j < TGSI_QUAD_SIZE; j++) {1125int x = itx + (j & 1);1126int y = ity + (j >> 1);1127for (i = 0; i < 4; i++) {1128dest[i][j] = tile->data.color[y][x][i];1129}1130}11311132/* If fixed-point dest color buffer, need to clamp the incoming1133* fragment colors now.1134*/1135if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) {1136clamp_colors(quadColor);1137}11381139VEC4_ADD(quadColor[0], quadColor[0], dest[0]); /* R */1140VEC4_ADD(quadColor[1], quadColor[1], dest[1]); /* G */1141VEC4_ADD(quadColor[2], quadColor[2], dest[2]); /* B */1142VEC4_ADD(quadColor[3], quadColor[3], dest[3]); /* A */11431144/* If fixed-point dest color buffer, need to clamp the outgoing1145* fragment colors now.1146*/1147if (bqs->clamp[0]) {1148clamp_colors(quadColor);1149}11501151rebase_colors(bqs->base_format[0], quadColor);11521153for (j = 0; j < TGSI_QUAD_SIZE; j++) {1154if (quad->inout.mask & (1 << j)) {1155int x = itx + (j & 1);1156int y = ity + (j >> 1);1157for (i = 0; i < 4; i++) { /* loop over color chans */1158tile->data.color[y][x][i] = quadColor[i][j];1159}1160}1161}1162}1163}116411651166/**1167* Just copy the quad color to the framebuffer tile (respecting the writemask),1168* for one color buffer.1169* Clamping will be done, if needed (depending on the color buffer's1170* datatype) when we write/pack the colors later.1171*/1172static void1173single_output_color(struct quad_stage *qs,1174struct quad_header *quads[],1175unsigned nr)1176{1177const struct blend_quad_stage *bqs = blend_quad_stage(qs);1178uint i, j, q;11791180struct softpipe_cached_tile *tile1181= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],1182quads[0]->input.x0,1183quads[0]->input.y0, quads[0]->input.layer);11841185for (q = 0; q < nr; q++) {1186struct quad_header *quad = quads[q];1187float (*quadColor)[4] = quad->output.color[0];1188const int itx = (quad->input.x0 & (TILE_SIZE-1));1189const int ity = (quad->input.y0 & (TILE_SIZE-1));11901191if (qs->softpipe->rasterizer->clamp_fragment_color)1192clamp_colors(quadColor);11931194rebase_colors(bqs->base_format[0], quadColor);11951196for (j = 0; j < TGSI_QUAD_SIZE; j++) {1197if (quad->inout.mask & (1 << j)) {1198int x = itx + (j & 1);1199int y = ity + (j >> 1);1200for (i = 0; i < 4; i++) { /* loop over color chans */1201tile->data.color[y][x][i] = quadColor[i][j];1202}1203}1204}1205}1206}12071208static void1209blend_noop(struct quad_stage *qs,1210struct quad_header *quads[],1211unsigned nr)1212{1213}121412151216static void1217choose_blend_quad(struct quad_stage *qs,1218struct quad_header *quads[],1219unsigned nr)1220{1221struct blend_quad_stage *bqs = blend_quad_stage(qs);1222struct softpipe_context *softpipe = qs->softpipe;1223const struct pipe_blend_state *blend = softpipe->blend;1224unsigned i;12251226qs->run = blend_fallback;12271228if (softpipe->framebuffer.nr_cbufs == 0) {1229qs->run = blend_noop;1230}1231else if (!softpipe->blend->logicop_enable &&1232softpipe->blend->rt[0].colormask == 0xf &&1233softpipe->framebuffer.nr_cbufs == 1)1234{1235if (softpipe->framebuffer.cbufs[0] == NULL) {1236qs->run = blend_noop;1237}1238else if (!blend->rt[0].blend_enable) {1239qs->run = single_output_color;1240}1241else if (blend->rt[0].rgb_src_factor == blend->rt[0].alpha_src_factor &&1242blend->rt[0].rgb_dst_factor == blend->rt[0].alpha_dst_factor &&1243blend->rt[0].rgb_func == blend->rt[0].alpha_func)1244{1245if (blend->rt[0].alpha_func == PIPE_BLEND_ADD) {1246if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_ONE &&1247blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_ONE) {1248qs->run = blend_single_add_one_one;1249}1250else if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA &&1251blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA)1252qs->run = blend_single_add_src_alpha_inv_src_alpha;12531254}1255}1256}12571258/* For each color buffer, determine if the buffer has destination alpha and1259* whether color clamping is needed.1260*/1261for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {1262if (softpipe->framebuffer.cbufs[i]) {1263const enum pipe_format format = softpipe->framebuffer.cbufs[i]->format;1264const struct util_format_description *desc =1265util_format_description(format);1266/* assuming all or no color channels are normalized: */1267bqs->clamp[i] = desc->channel[0].normalized;1268bqs->format_type[i] = desc->channel[0].type;12691270if (util_format_is_intensity(format))1271bqs->base_format[i] = INTENSITY;1272else if (util_format_is_luminance(format))1273bqs->base_format[i] = LUMINANCE;1274else if (util_format_is_luminance_alpha(format))1275bqs->base_format[i] = LUMINANCE_ALPHA;1276else if (!util_format_has_alpha(format))1277bqs->base_format[i] = RGB;1278else1279bqs->base_format[i] = RGBA;1280}1281}12821283qs->run(qs, quads, nr);1284}128512861287static void blend_begin(struct quad_stage *qs)1288{1289qs->run = choose_blend_quad;1290}129112921293static void blend_destroy(struct quad_stage *qs)1294{1295FREE( qs );1296}129712981299struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )1300{1301struct blend_quad_stage *stage = CALLOC_STRUCT(blend_quad_stage);13021303if (!stage)1304return NULL;13051306stage->base.softpipe = softpipe;1307stage->base.begin = blend_begin;1308stage->base.run = choose_blend_quad;1309stage->base.destroy = blend_destroy;13101311return &stage->base;1312}131313141315