1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (c) 2012-2015 Etnaviv Project 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 12bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 13bf215546Sopenharmony_ci * of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Wladimir J. van der Laan <laanwj@gmail.com> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "etnaviv_blend.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "etnaviv_context.h" 30bf215546Sopenharmony_ci#include "etnaviv_screen.h" 31bf215546Sopenharmony_ci#include "etnaviv_translate.h" 32bf215546Sopenharmony_ci#include "hw/common.xml.h" 33bf215546Sopenharmony_ci#include "pipe/p_defines.h" 34bf215546Sopenharmony_ci#include "util/u_memory.h" 35bf215546Sopenharmony_ci#include "util/half_float.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_civoid * 38bf215546Sopenharmony_cietna_blend_state_create(struct pipe_context *pctx, 39bf215546Sopenharmony_ci const struct pipe_blend_state *so) 40bf215546Sopenharmony_ci{ 41bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 42bf215546Sopenharmony_ci const struct pipe_rt_blend_state *rt0 = &so->rt[0]; 43bf215546Sopenharmony_ci struct etna_blend_state *co = CALLOC_STRUCT(etna_blend_state); 44bf215546Sopenharmony_ci bool alpha_enable, logicop_enable; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci /* pipe_blend_func happens to match the hardware. */ 47bf215546Sopenharmony_ci STATIC_ASSERT(PIPE_BLEND_ADD == BLEND_EQ_ADD); 48bf215546Sopenharmony_ci STATIC_ASSERT(PIPE_BLEND_SUBTRACT == BLEND_EQ_SUBTRACT); 49bf215546Sopenharmony_ci STATIC_ASSERT(PIPE_BLEND_REVERSE_SUBTRACT == BLEND_EQ_REVERSE_SUBTRACT); 50bf215546Sopenharmony_ci STATIC_ASSERT(PIPE_BLEND_MIN == BLEND_EQ_MIN); 51bf215546Sopenharmony_ci STATIC_ASSERT(PIPE_BLEND_MAX == BLEND_EQ_MAX); 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci if (!co) 54bf215546Sopenharmony_ci return NULL; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci co->base = *so; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci /* Enable blending if 59bf215546Sopenharmony_ci * - blend enabled in blend state 60bf215546Sopenharmony_ci * - NOT source factor is ONE and destination factor ZERO and eq is ADD for 61bf215546Sopenharmony_ci * both rgb and alpha (which mean that blending is effectively disabled) 62bf215546Sopenharmony_ci */ 63bf215546Sopenharmony_ci alpha_enable = rt0->blend_enable && 64bf215546Sopenharmony_ci !(rt0->rgb_src_factor == PIPE_BLENDFACTOR_ONE && 65bf215546Sopenharmony_ci rt0->rgb_dst_factor == PIPE_BLENDFACTOR_ZERO && 66bf215546Sopenharmony_ci rt0->rgb_func == PIPE_BLEND_ADD && 67bf215546Sopenharmony_ci rt0->alpha_src_factor == PIPE_BLENDFACTOR_ONE && 68bf215546Sopenharmony_ci rt0->alpha_dst_factor == PIPE_BLENDFACTOR_ZERO && 69bf215546Sopenharmony_ci rt0->alpha_func == PIPE_BLEND_ADD); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci /* Enable separate alpha if 72bf215546Sopenharmony_ci * - Blending enabled (see above) 73bf215546Sopenharmony_ci * - NOT source/destination factor and eq is same for both rgb and alpha 74bf215546Sopenharmony_ci * (which would effectively that mean alpha is not separate), and 75bf215546Sopenharmony_ci */ 76bf215546Sopenharmony_ci bool separate_alpha = alpha_enable && 77bf215546Sopenharmony_ci !(rt0->rgb_src_factor == rt0->alpha_src_factor && 78bf215546Sopenharmony_ci rt0->rgb_dst_factor == rt0->alpha_dst_factor && 79bf215546Sopenharmony_ci rt0->rgb_func == rt0->alpha_func); 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci if (alpha_enable) { 82bf215546Sopenharmony_ci co->PE_ALPHA_CONFIG = 83bf215546Sopenharmony_ci VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR | 84bf215546Sopenharmony_ci COND(separate_alpha, VIVS_PE_ALPHA_CONFIG_BLEND_SEPARATE_ALPHA) | 85bf215546Sopenharmony_ci VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR(translate_blend_factor(rt0->rgb_src_factor)) | 86bf215546Sopenharmony_ci VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA(translate_blend_factor(rt0->alpha_src_factor)) | 87bf215546Sopenharmony_ci VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR(translate_blend_factor(rt0->rgb_dst_factor)) | 88bf215546Sopenharmony_ci VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA(translate_blend_factor(rt0->alpha_dst_factor)) | 89bf215546Sopenharmony_ci VIVS_PE_ALPHA_CONFIG_EQ_COLOR(rt0->rgb_func) | 90bf215546Sopenharmony_ci VIVS_PE_ALPHA_CONFIG_EQ_ALPHA(rt0->alpha_func); 91bf215546Sopenharmony_ci } else { 92bf215546Sopenharmony_ci co->PE_ALPHA_CONFIG = 0; 93bf215546Sopenharmony_ci } 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci logicop_enable = so->logicop_enable && 96bf215546Sopenharmony_ci VIV_FEATURE(ctx->screen, chipMinorFeatures2, LOGIC_OP); 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci co->PE_LOGIC_OP = 99bf215546Sopenharmony_ci VIVS_PE_LOGIC_OP_OP(logicop_enable ? so->logicop_func : LOGIC_OP_COPY) | 100bf215546Sopenharmony_ci VIVS_PE_LOGIC_OP_DITHER_MODE(3) | /* TODO: related to dithering, sometimes 2 */ 101bf215546Sopenharmony_ci 0x000E4000 /* ??? */; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci co->fo_allowed = !alpha_enable && !logicop_enable; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci /* independent_blend_enable not needed: only one rt supported */ 106bf215546Sopenharmony_ci /* XXX alpha_to_coverage / alpha_to_one? */ 107bf215546Sopenharmony_ci /* Set dither registers based on dither status. These registers set the 108bf215546Sopenharmony_ci * dither pattern, 109bf215546Sopenharmony_ci * for now, set the same values as the blob. 110bf215546Sopenharmony_ci */ 111bf215546Sopenharmony_ci if (so->dither && 112bf215546Sopenharmony_ci (!alpha_enable || 113bf215546Sopenharmony_ci VIV_FEATURE(ctx->screen, chipMinorFeatures3, PE_DITHER_FIX))) { 114bf215546Sopenharmony_ci co->PE_DITHER[0] = 0x6e4ca280; 115bf215546Sopenharmony_ci co->PE_DITHER[1] = 0x5d7f91b3; 116bf215546Sopenharmony_ci } else { 117bf215546Sopenharmony_ci co->PE_DITHER[0] = 0xffffffff; 118bf215546Sopenharmony_ci co->PE_DITHER[1] = 0xffffffff; 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci return co; 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_cibool 125bf215546Sopenharmony_cietna_update_blend(struct etna_context *ctx) 126bf215546Sopenharmony_ci{ 127bf215546Sopenharmony_ci struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s; 128bf215546Sopenharmony_ci struct pipe_blend_state *pblend = ctx->blend; 129bf215546Sopenharmony_ci struct etna_blend_state *blend = etna_blend_state(pblend); 130bf215546Sopenharmony_ci const struct pipe_rt_blend_state *rt0 = &pblend->rt[0]; 131bf215546Sopenharmony_ci const struct util_format_description *desc; 132bf215546Sopenharmony_ci uint32_t colormask; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci if (pfb->cbufs[0] && 135bf215546Sopenharmony_ci translate_pe_format_rb_swap(pfb->cbufs[0]->format)) { 136bf215546Sopenharmony_ci colormask = rt0->colormask & (PIPE_MASK_A | PIPE_MASK_G); 137bf215546Sopenharmony_ci if (rt0->colormask & PIPE_MASK_R) 138bf215546Sopenharmony_ci colormask |= PIPE_MASK_B; 139bf215546Sopenharmony_ci if (rt0->colormask & PIPE_MASK_B) 140bf215546Sopenharmony_ci colormask |= PIPE_MASK_R; 141bf215546Sopenharmony_ci } else { 142bf215546Sopenharmony_ci colormask = rt0->colormask; 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci /* If the complete render target is written, set full_overwrite: 146bf215546Sopenharmony_ci * - The color mask covers all channels of the render target 147bf215546Sopenharmony_ci * - No blending or logicop is used 148bf215546Sopenharmony_ci */ 149bf215546Sopenharmony_ci if (pfb->cbufs[0]) 150bf215546Sopenharmony_ci desc = util_format_description(pfb->cbufs[0]->format); 151bf215546Sopenharmony_ci bool full_overwrite = !pfb->cbufs[0] || ((blend->fo_allowed && 152bf215546Sopenharmony_ci util_format_colormask_full(desc, colormask))); 153bf215546Sopenharmony_ci blend->PE_COLOR_FORMAT = 154bf215546Sopenharmony_ci VIVS_PE_COLOR_FORMAT_COMPONENTS(colormask) | 155bf215546Sopenharmony_ci COND(full_overwrite, VIVS_PE_COLOR_FORMAT_OVERWRITE); 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci return true; 158bf215546Sopenharmony_ci} 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_civoid 161bf215546Sopenharmony_cietna_set_blend_color(struct pipe_context *pctx, const struct pipe_blend_color *bc) 162bf215546Sopenharmony_ci{ 163bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 164bf215546Sopenharmony_ci struct compiled_blend_color *cs = &ctx->blend_color; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci memcpy(cs->color, bc->color, sizeof(float) * 4); 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_BLEND_COLOR; 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cibool 172bf215546Sopenharmony_cietna_update_blend_color(struct etna_context *ctx) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s; 175bf215546Sopenharmony_ci struct compiled_blend_color *cs = &ctx->blend_color; 176bf215546Sopenharmony_ci bool rb_swap = (pfb->cbufs[0] && translate_pe_format_rb_swap(pfb->cbufs[0]->format)); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci cs->PE_ALPHA_BLEND_COLOR = 179bf215546Sopenharmony_ci VIVS_PE_ALPHA_BLEND_COLOR_R(etna_cfloat_to_uint8(cs->color[rb_swap ? 2 : 0])) | 180bf215546Sopenharmony_ci VIVS_PE_ALPHA_BLEND_COLOR_G(etna_cfloat_to_uint8(cs->color[1])) | 181bf215546Sopenharmony_ci VIVS_PE_ALPHA_BLEND_COLOR_B(etna_cfloat_to_uint8(cs->color[rb_swap ? 0 : 2])) | 182bf215546Sopenharmony_ci VIVS_PE_ALPHA_BLEND_COLOR_A(etna_cfloat_to_uint8(cs->color[3])); 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci cs->PE_ALPHA_COLOR_EXT0 = 185bf215546Sopenharmony_ci VIVS_PE_ALPHA_COLOR_EXT0_B(_mesa_float_to_half(cs->color[rb_swap ? 2 : 0])) | 186bf215546Sopenharmony_ci VIVS_PE_ALPHA_COLOR_EXT0_G(_mesa_float_to_half(cs->color[1])); 187bf215546Sopenharmony_ci cs->PE_ALPHA_COLOR_EXT1 = 188bf215546Sopenharmony_ci VIVS_PE_ALPHA_COLOR_EXT1_R(_mesa_float_to_half(cs->color[rb_swap ? 0 : 2])) | 189bf215546Sopenharmony_ci VIVS_PE_ALPHA_COLOR_EXT1_A(_mesa_float_to_half(cs->color[3])); 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci return true; 192bf215546Sopenharmony_ci} 193