1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "util/u_inlines.h" 27bf215546Sopenharmony_ci#include "pipe/p_defines.h" 28bf215546Sopenharmony_ci#include "util/u_math.h" 29bf215546Sopenharmony_ci#include "util/format/u_format.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "svga_context.h" 32bf215546Sopenharmony_ci#include "svga_state.h" 33bf215546Sopenharmony_ci#include "svga_cmd.h" 34bf215546Sopenharmony_ci#include "svga_debug.h" 35bf215546Sopenharmony_ci#include "svga_screen.h" 36bf215546Sopenharmony_ci#include "svga_surface.h" 37bf215546Sopenharmony_ci#include "svga_resource_texture.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci/* 41bf215546Sopenharmony_ci * flush our command buffer after the 8th distinct render target 42bf215546Sopenharmony_ci * 43bf215546Sopenharmony_ci * This helps improve the surface cache behaviour in the face of the 44bf215546Sopenharmony_ci * large number of single-use render targets generated by EXA and the xorg 45bf215546Sopenharmony_ci * state tracker. Without this we can reference hundreds of individual 46bf215546Sopenharmony_ci * render targets from a command buffer, which leaves little scope for 47bf215546Sopenharmony_ci * sharing or reuse of those targets. 48bf215546Sopenharmony_ci */ 49bf215546Sopenharmony_ci#define MAX_RT_PER_BATCH 8 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic enum pipe_error 54bf215546Sopenharmony_ciemit_fb_vgpu9(struct svga_context *svga) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); 57bf215546Sopenharmony_ci const struct pipe_framebuffer_state *curr = &svga->curr.framebuffer; 58bf215546Sopenharmony_ci struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer; 59bf215546Sopenharmony_ci boolean reemit = svga->rebind.flags.rendertargets; 60bf215546Sopenharmony_ci unsigned i; 61bf215546Sopenharmony_ci enum pipe_error ret; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci assert(!svga_have_vgpu10(svga)); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci /* 66bf215546Sopenharmony_ci * We need to reemit non-null surface bindings, even when they are not 67bf215546Sopenharmony_ci * dirty, to ensure that the resources are paged in. 68bf215546Sopenharmony_ci */ 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci for (i = 0; i < svgascreen->max_color_buffers; i++) { 71bf215546Sopenharmony_ci if ((curr->cbufs[i] != hw->cbufs[i]) || (reemit && hw->cbufs[i])) { 72bf215546Sopenharmony_ci if (svga->curr.nr_fbs++ > MAX_RT_PER_BATCH) 73bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci /* Check to see if we need to propagate the render target surface */ 76bf215546Sopenharmony_ci if (hw->cbufs[i] && svga_surface_needs_propagation(hw->cbufs[i])) 77bf215546Sopenharmony_ci svga_propagate_surface(svga, hw->cbufs[i], TRUE); 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i, 80bf215546Sopenharmony_ci curr->cbufs[i]); 81bf215546Sopenharmony_ci if (ret != PIPE_OK) 82bf215546Sopenharmony_ci return ret; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]); 85bf215546Sopenharmony_ci } 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci /* Set the rendered-to flag */ 88bf215546Sopenharmony_ci struct pipe_surface *s = curr->cbufs[i]; 89bf215546Sopenharmony_ci if (s) { 90bf215546Sopenharmony_ci svga_set_texture_rendered_to(svga_texture(s->texture)); 91bf215546Sopenharmony_ci } 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci if ((curr->zsbuf != hw->zsbuf) || (reemit && hw->zsbuf)) { 95bf215546Sopenharmony_ci ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, curr->zsbuf); 96bf215546Sopenharmony_ci if (ret != PIPE_OK) 97bf215546Sopenharmony_ci return ret; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci /* Check to see if we need to propagate the depth stencil surface */ 100bf215546Sopenharmony_ci if (hw->zsbuf && svga_surface_needs_propagation(hw->zsbuf)) 101bf215546Sopenharmony_ci svga_propagate_surface(svga, hw->zsbuf, TRUE); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci if (curr->zsbuf && 104bf215546Sopenharmony_ci util_format_is_depth_and_stencil(curr->zsbuf->format)) { 105bf215546Sopenharmony_ci ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, 106bf215546Sopenharmony_ci curr->zsbuf); 107bf215546Sopenharmony_ci if (ret != PIPE_OK) 108bf215546Sopenharmony_ci return ret; 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci else { 111bf215546Sopenharmony_ci ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL); 112bf215546Sopenharmony_ci if (ret != PIPE_OK) 113bf215546Sopenharmony_ci return ret; 114bf215546Sopenharmony_ci } 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci pipe_surface_reference(&hw->zsbuf, curr->zsbuf); 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci /* Set the rendered-to flag */ 119bf215546Sopenharmony_ci struct pipe_surface *s = curr->zsbuf; 120bf215546Sopenharmony_ci if (s) { 121bf215546Sopenharmony_ci svga_set_texture_rendered_to(svga_texture(s->texture)); 122bf215546Sopenharmony_ci } 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci return PIPE_OK; 126bf215546Sopenharmony_ci} 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci/* 130bf215546Sopenharmony_ci * Rebind rendertargets. 131bf215546Sopenharmony_ci * 132bf215546Sopenharmony_ci * Similar to emit_framebuffer, but without any state checking/update. 133bf215546Sopenharmony_ci * 134bf215546Sopenharmony_ci * Called at the beginning of every new command buffer to ensure that 135bf215546Sopenharmony_ci * non-dirty rendertargets are properly paged-in. 136bf215546Sopenharmony_ci */ 137bf215546Sopenharmony_cistatic enum pipe_error 138bf215546Sopenharmony_cisvga_reemit_framebuffer_bindings_vgpu9(struct svga_context *svga) 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); 141bf215546Sopenharmony_ci struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer; 142bf215546Sopenharmony_ci unsigned i; 143bf215546Sopenharmony_ci enum pipe_error ret; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci assert(!svga_have_vgpu10(svga)); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci for (i = 0; i < svgascreen->max_color_buffers; i++) { 148bf215546Sopenharmony_ci if (hw->cbufs[i]) { 149bf215546Sopenharmony_ci ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i, 150bf215546Sopenharmony_ci hw->cbufs[i]); 151bf215546Sopenharmony_ci if (ret != PIPE_OK) { 152bf215546Sopenharmony_ci return ret; 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci } 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci if (hw->zsbuf) { 158bf215546Sopenharmony_ci ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, hw->zsbuf); 159bf215546Sopenharmony_ci if (ret != PIPE_OK) { 160bf215546Sopenharmony_ci return ret; 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci if (hw->zsbuf && 164bf215546Sopenharmony_ci util_format_is_depth_and_stencil(hw->zsbuf->format)) { 165bf215546Sopenharmony_ci ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, hw->zsbuf); 166bf215546Sopenharmony_ci if (ret != PIPE_OK) { 167bf215546Sopenharmony_ci return ret; 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci else { 171bf215546Sopenharmony_ci ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL); 172bf215546Sopenharmony_ci if (ret != PIPE_OK) { 173bf215546Sopenharmony_ci return ret; 174bf215546Sopenharmony_ci } 175bf215546Sopenharmony_ci } 176bf215546Sopenharmony_ci } 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci return PIPE_OK; 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_cistatic enum pipe_error 184bf215546Sopenharmony_ciemit_fb_vgpu10(struct svga_context *svga) 185bf215546Sopenharmony_ci{ 186bf215546Sopenharmony_ci const struct svga_screen *ss = svga_screen(svga->pipe.screen); 187bf215546Sopenharmony_ci struct pipe_surface *rtv[SVGA3D_MAX_RENDER_TARGETS]; 188bf215546Sopenharmony_ci struct pipe_surface *dsv; 189bf215546Sopenharmony_ci struct pipe_framebuffer_state *curr = &svga->curr.framebuffer; 190bf215546Sopenharmony_ci struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer; 191bf215546Sopenharmony_ci const unsigned num_color = MAX2(curr->nr_cbufs, hw->nr_cbufs); 192bf215546Sopenharmony_ci int last_rtv = -1; 193bf215546Sopenharmony_ci unsigned i; 194bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci /* Reset the has_backed_views flag. 199bf215546Sopenharmony_ci * The flag is set in svga_validate_surface_view() if 200bf215546Sopenharmony_ci * a backed surface view is used. 201bf215546Sopenharmony_ci */ 202bf215546Sopenharmony_ci svga->state.hw_draw.has_backed_views = FALSE; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci /* Setup render targets array. Note that we loop over the max of the 205bf215546Sopenharmony_ci * number of previously bound buffers and the new buffers to unbind 206bf215546Sopenharmony_ci * any previously bound buffers when the new number of buffers is less 207bf215546Sopenharmony_ci * than the old number of buffers. 208bf215546Sopenharmony_ci */ 209bf215546Sopenharmony_ci for (i = 0; i < num_color; i++) { 210bf215546Sopenharmony_ci if (curr->cbufs[i]) { 211bf215546Sopenharmony_ci struct pipe_surface *s = curr->cbufs[i]; 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci if (curr->cbufs[i] != hw->cbufs[i]) { 214bf215546Sopenharmony_ci rtv[i] = svga_validate_surface_view(svga, svga_surface(s)); 215bf215546Sopenharmony_ci if (rtv[i] == NULL) { 216bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci } else { 219bf215546Sopenharmony_ci rtv[i] = svga->state.hw_clear.rtv[i]; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci assert(svga_surface(rtv[i])->view_id != SVGA3D_INVALID_ID); 223bf215546Sopenharmony_ci last_rtv = i; 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci /* Set the rendered-to flag */ 226bf215546Sopenharmony_ci svga_set_texture_rendered_to(svga_texture(s->texture)); 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci else { 229bf215546Sopenharmony_ci rtv[i] = NULL; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci /* Setup depth stencil view */ 234bf215546Sopenharmony_ci if (curr->zsbuf) { 235bf215546Sopenharmony_ci struct pipe_surface *s = curr->zsbuf; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci if (curr->zsbuf != hw->zsbuf) { 238bf215546Sopenharmony_ci dsv = svga_validate_surface_view(svga, svga_surface(curr->zsbuf)); 239bf215546Sopenharmony_ci if (!dsv) { 240bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci } else { 243bf215546Sopenharmony_ci dsv = svga->state.hw_clear.dsv; 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci /* Set the rendered-to flag */ 247bf215546Sopenharmony_ci svga_set_texture_rendered_to(svga_texture(s->texture)); 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci else { 250bf215546Sopenharmony_ci dsv = NULL; 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci /* avoid emitting redundant SetRenderTargets command */ 254bf215546Sopenharmony_ci if ((num_color != svga->state.hw_clear.num_rendertargets) || 255bf215546Sopenharmony_ci (dsv != svga->state.hw_clear.dsv) || 256bf215546Sopenharmony_ci memcmp(rtv, svga->state.hw_clear.rtv, num_color * sizeof(rtv[0]))) { 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetRenderTargets(svga->swc, num_color, rtv, dsv); 259bf215546Sopenharmony_ci if (ret != PIPE_OK) 260bf215546Sopenharmony_ci return ret; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci /* number of render targets sent to the device, not including trailing 263bf215546Sopenharmony_ci * unbound render targets. 264bf215546Sopenharmony_ci */ 265bf215546Sopenharmony_ci for (i = 0; i < ss->max_color_buffers; i++) { 266bf215546Sopenharmony_ci if (hw->cbufs[i] != curr->cbufs[i]) { 267bf215546Sopenharmony_ci /* propagate the backed view surface before unbinding it */ 268bf215546Sopenharmony_ci if (hw->cbufs[i] && svga_surface(hw->cbufs[i])->backed) { 269bf215546Sopenharmony_ci svga_propagate_surface(svga, 270bf215546Sopenharmony_ci &svga_surface(hw->cbufs[i])->backed->base, 271bf215546Sopenharmony_ci TRUE); 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci else if (svga->state.hw_clear.rtv[i] != hw->cbufs[i] && 274bf215546Sopenharmony_ci svga->state.hw_clear.rtv[i]) { 275bf215546Sopenharmony_ci /* Free the alternate surface view when it is unbound. */ 276bf215546Sopenharmony_ci svga->pipe.surface_destroy(&svga->pipe, svga->state.hw_clear.rtv[i]); 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]); 279bf215546Sopenharmony_ci } 280bf215546Sopenharmony_ci } 281bf215546Sopenharmony_ci svga->state.hw_clear.num_rendertargets = last_rtv + 1; 282bf215546Sopenharmony_ci memcpy(svga->state.hw_clear.rtv, rtv, num_color * sizeof(rtv[0])); 283bf215546Sopenharmony_ci hw->nr_cbufs = curr->nr_cbufs; 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (hw->zsbuf != curr->zsbuf) { 286bf215546Sopenharmony_ci /* propagate the backed view surface before unbinding it */ 287bf215546Sopenharmony_ci if (hw->zsbuf && svga_surface(hw->zsbuf)->backed) { 288bf215546Sopenharmony_ci svga_propagate_surface(svga, 289bf215546Sopenharmony_ci &svga_surface(hw->zsbuf)->backed->base, 290bf215546Sopenharmony_ci TRUE); 291bf215546Sopenharmony_ci } 292bf215546Sopenharmony_ci else if (svga->state.hw_clear.dsv != hw->zsbuf && svga->state.hw_clear.dsv) { 293bf215546Sopenharmony_ci /* Free the alternate surface view when it is unbound. */ 294bf215546Sopenharmony_ci svga->pipe.surface_destroy(&svga->pipe, svga->state.hw_clear.dsv); 295bf215546Sopenharmony_ci } 296bf215546Sopenharmony_ci pipe_surface_reference(&hw->zsbuf, curr->zsbuf); 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci svga->state.hw_clear.dsv = dsv; 299bf215546Sopenharmony_ci } 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci return ret; 302bf215546Sopenharmony_ci} 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_cistatic enum pipe_error 306bf215546Sopenharmony_ciemit_framebuffer(struct svga_context *svga, uint64_t dirty) 307bf215546Sopenharmony_ci{ 308bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 309bf215546Sopenharmony_ci return emit_fb_vgpu10(svga); 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci else { 312bf215546Sopenharmony_ci return emit_fb_vgpu9(svga); 313bf215546Sopenharmony_ci } 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci/* 318bf215546Sopenharmony_ci * Rebind rendertargets. 319bf215546Sopenharmony_ci * 320bf215546Sopenharmony_ci * Similar to emit_framebuffer, but without any state checking/update. 321bf215546Sopenharmony_ci * 322bf215546Sopenharmony_ci * Called at the beginning of every new command buffer to ensure that 323bf215546Sopenharmony_ci * non-dirty rendertargets are properly paged-in. 324bf215546Sopenharmony_ci */ 325bf215546Sopenharmony_cienum pipe_error 326bf215546Sopenharmony_cisvga_reemit_framebuffer_bindings(struct svga_context *svga) 327bf215546Sopenharmony_ci{ 328bf215546Sopenharmony_ci enum pipe_error ret; 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci assert(svga->rebind.flags.rendertargets); 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 333bf215546Sopenharmony_ci ret = emit_fb_vgpu10(svga); 334bf215546Sopenharmony_ci } 335bf215546Sopenharmony_ci else { 336bf215546Sopenharmony_ci ret = svga_reemit_framebuffer_bindings_vgpu9(svga); 337bf215546Sopenharmony_ci } 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci svga->rebind.flags.rendertargets = FALSE; 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci return ret; 342bf215546Sopenharmony_ci} 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci/* 346bf215546Sopenharmony_ci * Send a private allocation command to page in rendertargets resource. 347bf215546Sopenharmony_ci */ 348bf215546Sopenharmony_cienum pipe_error 349bf215546Sopenharmony_cisvga_rebind_framebuffer_bindings(struct svga_context *svga) 350bf215546Sopenharmony_ci{ 351bf215546Sopenharmony_ci struct svga_hw_clear_state *hw = &svga->state.hw_clear; 352bf215546Sopenharmony_ci unsigned i; 353bf215546Sopenharmony_ci enum pipe_error ret; 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci if (!svga->rebind.flags.rendertargets) 358bf215546Sopenharmony_ci return PIPE_OK; 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci for (i = 0; i < hw->num_rendertargets; i++) { 361bf215546Sopenharmony_ci if (hw->rtv[i]) { 362bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, 363bf215546Sopenharmony_ci svga_surface(hw->rtv[i])->handle, 364bf215546Sopenharmony_ci NULL, 365bf215546Sopenharmony_ci SVGA_RELOC_WRITE); 366bf215546Sopenharmony_ci if (ret != PIPE_OK) 367bf215546Sopenharmony_ci return ret; 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (hw->dsv) { 372bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, 373bf215546Sopenharmony_ci svga_surface(hw->dsv)->handle, 374bf215546Sopenharmony_ci NULL, 375bf215546Sopenharmony_ci SVGA_RELOC_WRITE); 376bf215546Sopenharmony_ci if (ret != PIPE_OK) 377bf215546Sopenharmony_ci return ret; 378bf215546Sopenharmony_ci } 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci svga->rebind.flags.rendertargets = 0; 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci return PIPE_OK; 383bf215546Sopenharmony_ci} 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_framebuffer = 387bf215546Sopenharmony_ci{ 388bf215546Sopenharmony_ci "hw framebuffer state", 389bf215546Sopenharmony_ci SVGA_NEW_FRAME_BUFFER, 390bf215546Sopenharmony_ci emit_framebuffer 391bf215546Sopenharmony_ci}; 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci/*********************************************************************** 397bf215546Sopenharmony_ci */ 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_cistatic void 400bf215546Sopenharmony_ciget_viewport_prescale(struct svga_context *svga, 401bf215546Sopenharmony_ci struct pipe_viewport_state *viewport, 402bf215546Sopenharmony_ci SVGA3dViewport *vp, 403bf215546Sopenharmony_ci struct svga_prescale *prescale) 404bf215546Sopenharmony_ci{ 405bf215546Sopenharmony_ci SVGA3dRect rect; 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci /* Not sure if this state is relevant with POSITIONT. Probably 408bf215546Sopenharmony_ci * not, but setting to 0,1 avoids some state pingponging. 409bf215546Sopenharmony_ci */ 410bf215546Sopenharmony_ci float range_min = 0.0; 411bf215546Sopenharmony_ci float range_max = 1.0; 412bf215546Sopenharmony_ci float flip = -1.0; 413bf215546Sopenharmony_ci boolean degenerate = FALSE; 414bf215546Sopenharmony_ci boolean invertY = FALSE; 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci float fb_width = (float) svga->curr.framebuffer.width; 417bf215546Sopenharmony_ci float fb_height = (float) svga->curr.framebuffer.height; 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci float fx = viewport->scale[0] * -1.0f + viewport->translate[0]; 420bf215546Sopenharmony_ci float fy = flip * viewport->scale[1] * -1.0f + viewport->translate[1]; 421bf215546Sopenharmony_ci float fw = viewport->scale[0] * 2.0f; 422bf215546Sopenharmony_ci float fh = flip * viewport->scale[1] * 2.0f; 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci memset(prescale, 0, sizeof(*prescale)); 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci /* Examine gallium viewport transformation and produce a screen 427bf215546Sopenharmony_ci * rectangle and possibly vertex shader pre-transformation to 428bf215546Sopenharmony_ci * get the same results. 429bf215546Sopenharmony_ci */ 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci SVGA_DBG(DEBUG_VIEWPORT, 432bf215546Sopenharmony_ci "\ninitial %f,%f %fx%f\n", 433bf215546Sopenharmony_ci fx, 434bf215546Sopenharmony_ci fy, 435bf215546Sopenharmony_ci fw, 436bf215546Sopenharmony_ci fh); 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci prescale->scale[0] = 1.0; 439bf215546Sopenharmony_ci prescale->scale[1] = 1.0; 440bf215546Sopenharmony_ci prescale->scale[2] = 1.0; 441bf215546Sopenharmony_ci prescale->scale[3] = 1.0; 442bf215546Sopenharmony_ci prescale->translate[0] = 0; 443bf215546Sopenharmony_ci prescale->translate[1] = 0; 444bf215546Sopenharmony_ci prescale->translate[2] = 0; 445bf215546Sopenharmony_ci prescale->translate[3] = 0; 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci /* Enable prescale to adjust vertex positions to match 448bf215546Sopenharmony_ci VGPU10 convention only if rasterization is enabled. 449bf215546Sopenharmony_ci */ 450bf215546Sopenharmony_ci if (svga->curr.rast && svga->curr.rast->templ.rasterizer_discard) { 451bf215546Sopenharmony_ci degenerate = TRUE; 452bf215546Sopenharmony_ci goto out; 453bf215546Sopenharmony_ci } else { 454bf215546Sopenharmony_ci prescale->enabled = TRUE; 455bf215546Sopenharmony_ci } 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci if (fw < 0) { 458bf215546Sopenharmony_ci prescale->scale[0] *= -1.0f; 459bf215546Sopenharmony_ci prescale->translate[0] += -fw; 460bf215546Sopenharmony_ci fw = -fw; 461bf215546Sopenharmony_ci fx = viewport->scale[0] * 1.0f + viewport->translate[0]; 462bf215546Sopenharmony_ci } 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci if (fh < 0.0) { 465bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 466bf215546Sopenharmony_ci /* floating point viewport params below */ 467bf215546Sopenharmony_ci prescale->translate[1] = fh + fy * 2.0f; 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci else { 470bf215546Sopenharmony_ci /* integer viewport params below */ 471bf215546Sopenharmony_ci prescale->translate[1] = fh - 1.0f + fy * 2.0f; 472bf215546Sopenharmony_ci } 473bf215546Sopenharmony_ci fh = -fh; 474bf215546Sopenharmony_ci fy -= fh; 475bf215546Sopenharmony_ci prescale->scale[1] = -1.0f; 476bf215546Sopenharmony_ci invertY = TRUE; 477bf215546Sopenharmony_ci } 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci if (fx < 0) { 480bf215546Sopenharmony_ci prescale->translate[0] += fx; 481bf215546Sopenharmony_ci prescale->scale[0] *= fw / (fw + fx); 482bf215546Sopenharmony_ci fw += fx; 483bf215546Sopenharmony_ci fx = 0.0f; 484bf215546Sopenharmony_ci } 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci if (fy < 0) { 487bf215546Sopenharmony_ci if (invertY) { 488bf215546Sopenharmony_ci prescale->translate[1] -= fy; 489bf215546Sopenharmony_ci } 490bf215546Sopenharmony_ci else { 491bf215546Sopenharmony_ci prescale->translate[1] += fy; 492bf215546Sopenharmony_ci } 493bf215546Sopenharmony_ci prescale->scale[1] *= fh / (fh + fy); 494bf215546Sopenharmony_ci fh += fy; 495bf215546Sopenharmony_ci fy = 0.0f; 496bf215546Sopenharmony_ci } 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci if (fx + fw > fb_width) { 499bf215546Sopenharmony_ci prescale->scale[0] *= fw / (fb_width - fx); 500bf215546Sopenharmony_ci prescale->translate[0] -= fx * (fw / (fb_width - fx)); 501bf215546Sopenharmony_ci prescale->translate[0] += fx; 502bf215546Sopenharmony_ci fw = fb_width - fx; 503bf215546Sopenharmony_ci } 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci if (fy + fh > fb_height) { 506bf215546Sopenharmony_ci prescale->scale[1] *= fh / (fb_height - fy); 507bf215546Sopenharmony_ci if (invertY) { 508bf215546Sopenharmony_ci float in = fb_height - fy; /* number of vp pixels inside view */ 509bf215546Sopenharmony_ci float out = fy + fh - fb_height; /* number of vp pixels out of view */ 510bf215546Sopenharmony_ci prescale->translate[1] += fy * out / in; 511bf215546Sopenharmony_ci } 512bf215546Sopenharmony_ci else { 513bf215546Sopenharmony_ci prescale->translate[1] -= fy * (fh / (fb_height - fy)); 514bf215546Sopenharmony_ci prescale->translate[1] += fy; 515bf215546Sopenharmony_ci } 516bf215546Sopenharmony_ci fh = fb_height - fy; 517bf215546Sopenharmony_ci } 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci if (fw < 0 || fh < 0) { 520bf215546Sopenharmony_ci fw = fh = fx = fy = 0; 521bf215546Sopenharmony_ci degenerate = TRUE; 522bf215546Sopenharmony_ci goto out; 523bf215546Sopenharmony_ci } 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci /* D3D viewport is integer space. Convert fx,fy,etc. to 526bf215546Sopenharmony_ci * integers. 527bf215546Sopenharmony_ci * 528bf215546Sopenharmony_ci * TODO: adjust pretranslate correct for any subpixel error 529bf215546Sopenharmony_ci * introduced converting to integers. 530bf215546Sopenharmony_ci */ 531bf215546Sopenharmony_ci rect.x = (uint32) fx; 532bf215546Sopenharmony_ci rect.y = (uint32) fy; 533bf215546Sopenharmony_ci rect.w = (uint32) fw; 534bf215546Sopenharmony_ci rect.h = (uint32) fh; 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci SVGA_DBG(DEBUG_VIEWPORT, 537bf215546Sopenharmony_ci "viewport error %f,%f %fx%f\n", 538bf215546Sopenharmony_ci fabs((float)rect.x - fx), 539bf215546Sopenharmony_ci fabs((float)rect.y - fy), 540bf215546Sopenharmony_ci fabs((float)rect.w - fw), 541bf215546Sopenharmony_ci fabs((float)rect.h - fh)); 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci SVGA_DBG(DEBUG_VIEWPORT, 544bf215546Sopenharmony_ci "viewport %d,%d %dx%d\n", 545bf215546Sopenharmony_ci rect.x, 546bf215546Sopenharmony_ci rect.y, 547bf215546Sopenharmony_ci rect.w, 548bf215546Sopenharmony_ci rect.h); 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci /* Finally, to get GL rasterization rules, need to tweak the 551bf215546Sopenharmony_ci * screen-space coordinates slightly relative to D3D which is 552bf215546Sopenharmony_ci * what hardware implements natively. 553bf215546Sopenharmony_ci */ 554bf215546Sopenharmony_ci if (svga->curr.rast && svga->curr.rast->templ.half_pixel_center) { 555bf215546Sopenharmony_ci float adjust_x = 0.0; 556bf215546Sopenharmony_ci float adjust_y = 0.0; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 559bf215546Sopenharmony_ci /* Normally, we don't have to do any sub-pixel coordinate 560bf215546Sopenharmony_ci * adjustments for VGPU10. But when we draw wide points with 561bf215546Sopenharmony_ci * a GS we need an X adjustment in order to be conformant. 562bf215546Sopenharmony_ci */ 563bf215546Sopenharmony_ci if (svga->curr.reduced_prim == PIPE_PRIM_POINTS && 564bf215546Sopenharmony_ci svga->curr.rast->pointsize > 1.0f) { 565bf215546Sopenharmony_ci adjust_x = 0.5; 566bf215546Sopenharmony_ci } 567bf215546Sopenharmony_ci } 568bf215546Sopenharmony_ci else { 569bf215546Sopenharmony_ci /* Use (-0.5, -0.5) bias for all prim types. 570bf215546Sopenharmony_ci * Regarding line rasterization, this does not seem to satisfy 571bf215546Sopenharmony_ci * the Piglit gl-1.0-ortho-pos test but it generally produces 572bf215546Sopenharmony_ci * results identical or very similar to VGPU10. 573bf215546Sopenharmony_ci */ 574bf215546Sopenharmony_ci adjust_x = -0.5; 575bf215546Sopenharmony_ci adjust_y = -0.5; 576bf215546Sopenharmony_ci } 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci if (invertY) 579bf215546Sopenharmony_ci adjust_y = -adjust_y; 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_ci prescale->translate[0] += adjust_x; 582bf215546Sopenharmony_ci prescale->translate[1] += adjust_y; 583bf215546Sopenharmony_ci prescale->translate[2] = 0.5; /* D3D clip space */ 584bf215546Sopenharmony_ci prescale->scale[2] = 0.5; /* D3D clip space */ 585bf215546Sopenharmony_ci } 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci range_min = viewport->scale[2] * -1.0f + viewport->translate[2]; 588bf215546Sopenharmony_ci range_max = viewport->scale[2] * 1.0f + viewport->translate[2]; 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci /* D3D (and by implication SVGA) doesn't like dealing with zmax 591bf215546Sopenharmony_ci * less than zmin. Detect that case, flip the depth range and 592bf215546Sopenharmony_ci * invert our z-scale factor to achieve the same effect. 593bf215546Sopenharmony_ci */ 594bf215546Sopenharmony_ci if (range_min > range_max) { 595bf215546Sopenharmony_ci float range_tmp; 596bf215546Sopenharmony_ci range_tmp = range_min; 597bf215546Sopenharmony_ci range_min = range_max; 598bf215546Sopenharmony_ci range_max = range_tmp; 599bf215546Sopenharmony_ci prescale->scale[2] = -prescale->scale[2]; 600bf215546Sopenharmony_ci } 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci /* If zmin is less than 0, clamp zmin to 0 and adjust the prescale. 603bf215546Sopenharmony_ci * zmin can be set to -1 when viewport->scale[2] is set to 1 and 604bf215546Sopenharmony_ci * viewport->translate[2] is set to 0 in the blit code. 605bf215546Sopenharmony_ci */ 606bf215546Sopenharmony_ci if (range_min < 0.0f) { 607bf215546Sopenharmony_ci range_min = -0.5f * viewport->scale[2] + 0.5f + viewport->translate[2]; 608bf215546Sopenharmony_ci range_max = 0.5f * viewport->scale[2] + 0.5f + viewport->translate[2]; 609bf215546Sopenharmony_ci prescale->scale[2] *= 2.0f; 610bf215546Sopenharmony_ci prescale->translate[2] -= 0.5f; 611bf215546Sopenharmony_ci } 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci /* Clamp depth range, making sure it's between 0 and 1 */ 614bf215546Sopenharmony_ci range_min = CLAMP(range_min, 0.0f, 1.0f); 615bf215546Sopenharmony_ci range_max = CLAMP(range_max, 0.0f, 1.0f); 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci if (prescale->enabled) { 618bf215546Sopenharmony_ci float H[2]; 619bf215546Sopenharmony_ci float J[2]; 620bf215546Sopenharmony_ci int i; 621bf215546Sopenharmony_ci 622bf215546Sopenharmony_ci SVGA_DBG(DEBUG_VIEWPORT, 623bf215546Sopenharmony_ci "prescale %f,%f %fx%f\n", 624bf215546Sopenharmony_ci prescale->translate[0], 625bf215546Sopenharmony_ci prescale->translate[1], 626bf215546Sopenharmony_ci prescale->scale[0], 627bf215546Sopenharmony_ci prescale->scale[1]); 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci H[0] = (float)rect.w / 2.0f; 630bf215546Sopenharmony_ci H[1] = -(float)rect.h / 2.0f; 631bf215546Sopenharmony_ci J[0] = (float)rect.x + (float)rect.w / 2.0f; 632bf215546Sopenharmony_ci J[1] = (float)rect.y + (float)rect.h / 2.0f; 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci SVGA_DBG(DEBUG_VIEWPORT, 635bf215546Sopenharmony_ci "H %f,%f\n" 636bf215546Sopenharmony_ci "J %fx%f\n", 637bf215546Sopenharmony_ci H[0], 638bf215546Sopenharmony_ci H[1], 639bf215546Sopenharmony_ci J[0], 640bf215546Sopenharmony_ci J[1]); 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_ci /* Adjust prescale to take into account the fact that it is 643bf215546Sopenharmony_ci * going to be applied prior to the perspective divide and 644bf215546Sopenharmony_ci * viewport transformation. 645bf215546Sopenharmony_ci * 646bf215546Sopenharmony_ci * Vwin = H(Vc/Vc.w) + J 647bf215546Sopenharmony_ci * 648bf215546Sopenharmony_ci * We want to tweak Vwin with scale and translation from above, 649bf215546Sopenharmony_ci * as in: 650bf215546Sopenharmony_ci * 651bf215546Sopenharmony_ci * Vwin' = S Vwin + T 652bf215546Sopenharmony_ci * 653bf215546Sopenharmony_ci * But we can only modify the values at Vc. Plugging all the 654bf215546Sopenharmony_ci * above together, and rearranging, eventually we get: 655bf215546Sopenharmony_ci * 656bf215546Sopenharmony_ci * Vwin' = H(Vc'/Vc'.w) + J 657bf215546Sopenharmony_ci * where: 658bf215546Sopenharmony_ci * Vc' = SVc + KVc.w 659bf215546Sopenharmony_ci * K = (T + (S-1)J) / H 660bf215546Sopenharmony_ci * 661bf215546Sopenharmony_ci * Overwrite prescale.translate with values for K: 662bf215546Sopenharmony_ci */ 663bf215546Sopenharmony_ci for (i = 0; i < 2; i++) { 664bf215546Sopenharmony_ci prescale->translate[i] = ((prescale->translate[i] + 665bf215546Sopenharmony_ci (prescale->scale[i] - 1.0f) * J[i]) / H[i]); 666bf215546Sopenharmony_ci } 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci SVGA_DBG(DEBUG_VIEWPORT, 669bf215546Sopenharmony_ci "clipspace %f,%f %fx%f\n", 670bf215546Sopenharmony_ci prescale->translate[0], 671bf215546Sopenharmony_ci prescale->translate[1], 672bf215546Sopenharmony_ci prescale->scale[0], 673bf215546Sopenharmony_ci prescale->scale[1]); 674bf215546Sopenharmony_ci } 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ciout: 677bf215546Sopenharmony_ci if (degenerate) { 678bf215546Sopenharmony_ci rect.x = 0; 679bf215546Sopenharmony_ci rect.y = 0; 680bf215546Sopenharmony_ci rect.w = 1; 681bf215546Sopenharmony_ci rect.h = 1; 682bf215546Sopenharmony_ci prescale->enabled = FALSE; 683bf215546Sopenharmony_ci } 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci vp->x = (float) rect.x; 686bf215546Sopenharmony_ci vp->y = (float) rect.y; 687bf215546Sopenharmony_ci vp->width = (float) rect.w; 688bf215546Sopenharmony_ci vp->height = (float) rect.h; 689bf215546Sopenharmony_ci vp->minDepth = range_min; 690bf215546Sopenharmony_ci vp->maxDepth = range_max; 691bf215546Sopenharmony_ci} 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_cistatic enum pipe_error 695bf215546Sopenharmony_ciemit_viewport( struct svga_context *svga, 696bf215546Sopenharmony_ci uint64_t dirty ) 697bf215546Sopenharmony_ci{ 698bf215546Sopenharmony_ci struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); 699bf215546Sopenharmony_ci SVGA3dViewport viewports[SVGA3D_DX_MAX_VIEWPORTS]; 700bf215546Sopenharmony_ci struct svga_prescale prescale[SVGA3D_DX_MAX_VIEWPORTS]; 701bf215546Sopenharmony_ci unsigned i; 702bf215546Sopenharmony_ci enum pipe_error ret; 703bf215546Sopenharmony_ci unsigned max_viewports = svgascreen->max_viewports; 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ci for (i = 0; i < max_viewports; i++) { 706bf215546Sopenharmony_ci get_viewport_prescale(svga, &svga->curr.viewport[i], 707bf215546Sopenharmony_ci &viewports[i], &prescale[i]); 708bf215546Sopenharmony_ci } 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci if (memcmp(viewports, svga->state.hw_clear.viewports, 711bf215546Sopenharmony_ci max_viewports * sizeof viewports[0]) != 0) { 712bf215546Sopenharmony_ci 713bf215546Sopenharmony_ci if (!svga_have_vgpu10(svga)) { 714bf215546Sopenharmony_ci SVGA3dRect rect; 715bf215546Sopenharmony_ci SVGA3dViewport *vp = &viewports[0]; 716bf215546Sopenharmony_ci 717bf215546Sopenharmony_ci rect.x = (uint32)vp->x; 718bf215546Sopenharmony_ci rect.y = (uint32)vp->y; 719bf215546Sopenharmony_ci rect.w = (uint32)vp->width; 720bf215546Sopenharmony_ci rect.h = (uint32)vp->height; 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_ci ret = SVGA3D_SetViewport(svga->swc, &rect); 723bf215546Sopenharmony_ci if (ret != PIPE_OK) 724bf215546Sopenharmony_ci return ret; 725bf215546Sopenharmony_ci 726bf215546Sopenharmony_ci ret = SVGA3D_SetZRange(svga->swc, vp->minDepth, vp->maxDepth); 727bf215546Sopenharmony_ci if (ret != PIPE_OK) 728bf215546Sopenharmony_ci return ret; 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci svga->state.hw_clear.viewport = rect; 731bf215546Sopenharmony_ci svga->state.hw_clear.depthrange.zmin = vp->minDepth; 732bf215546Sopenharmony_ci svga->state.hw_clear.depthrange.zmax = vp->maxDepth; 733bf215546Sopenharmony_ci } 734bf215546Sopenharmony_ci else { 735bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetViewports(svga->swc, max_viewports, 736bf215546Sopenharmony_ci viewports); 737bf215546Sopenharmony_ci if (ret != PIPE_OK) 738bf215546Sopenharmony_ci return ret; 739bf215546Sopenharmony_ci } 740bf215546Sopenharmony_ci memcpy(svga->state.hw_clear.viewports, viewports, 741bf215546Sopenharmony_ci max_viewports * sizeof viewports[0]); 742bf215546Sopenharmony_ci } 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_ci if (memcmp(prescale, svga->state.hw_clear.prescale, 745bf215546Sopenharmony_ci max_viewports * sizeof prescale[0]) != 0) { 746bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_PRESCALE; 747bf215546Sopenharmony_ci memcpy(svga->state.hw_clear.prescale, prescale, 748bf215546Sopenharmony_ci max_viewports * sizeof prescale[0]); 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_ci /* 751bf215546Sopenharmony_ci * Determine number of unique prescales. This is to minimize the 752bf215546Sopenharmony_ci * if check needed in the geometry shader to identify the prescale 753bf215546Sopenharmony_ci * for the specified viewport. 754bf215546Sopenharmony_ci */ 755bf215546Sopenharmony_ci unsigned last_prescale = SVGA3D_DX_MAX_VIEWPORTS - 1; 756bf215546Sopenharmony_ci unsigned i; 757bf215546Sopenharmony_ci for (i = SVGA3D_DX_MAX_VIEWPORTS-1; i > 0; i--) { 758bf215546Sopenharmony_ci if (memcmp(&svga->state.hw_clear.prescale[i], 759bf215546Sopenharmony_ci &svga->state.hw_clear.prescale[i-1], 760bf215546Sopenharmony_ci sizeof svga->state.hw_clear.prescale[0])) { 761bf215546Sopenharmony_ci break; 762bf215546Sopenharmony_ci } 763bf215546Sopenharmony_ci last_prescale--; 764bf215546Sopenharmony_ci } 765bf215546Sopenharmony_ci svga->state.hw_clear.num_prescale = last_prescale + 1; 766bf215546Sopenharmony_ci } 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci return PIPE_OK; 769bf215546Sopenharmony_ci} 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_viewport = 773bf215546Sopenharmony_ci{ 774bf215546Sopenharmony_ci "hw viewport state", 775bf215546Sopenharmony_ci ( SVGA_NEW_FRAME_BUFFER | 776bf215546Sopenharmony_ci SVGA_NEW_VIEWPORT | 777bf215546Sopenharmony_ci SVGA_NEW_RAST | 778bf215546Sopenharmony_ci SVGA_NEW_REDUCED_PRIMITIVE ), 779bf215546Sopenharmony_ci emit_viewport 780bf215546Sopenharmony_ci}; 781bf215546Sopenharmony_ci 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_ci/*********************************************************************** 784bf215546Sopenharmony_ci * Scissor state 785bf215546Sopenharmony_ci */ 786bf215546Sopenharmony_cistatic enum pipe_error 787bf215546Sopenharmony_ciemit_scissor_rect( struct svga_context *svga, 788bf215546Sopenharmony_ci uint64_t dirty ) 789bf215546Sopenharmony_ci{ 790bf215546Sopenharmony_ci struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); 791bf215546Sopenharmony_ci const struct pipe_scissor_state *scissor = svga->curr.scissor; 792bf215546Sopenharmony_ci unsigned max_viewports = svgascreen->max_viewports; 793bf215546Sopenharmony_ci enum pipe_error ret; 794bf215546Sopenharmony_ci 795bf215546Sopenharmony_ci if (memcmp(&svga->state.hw_clear.scissors[0], scissor, 796bf215546Sopenharmony_ci max_viewports * sizeof *scissor) != 0) { 797bf215546Sopenharmony_ci 798bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 799bf215546Sopenharmony_ci SVGASignedRect rect[SVGA3D_DX_MAX_VIEWPORTS]; 800bf215546Sopenharmony_ci unsigned i; 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci for (i = 0; i < max_viewports; i++) { 803bf215546Sopenharmony_ci rect[i].left = scissor[i].minx; 804bf215546Sopenharmony_ci rect[i].top = scissor[i].miny; 805bf215546Sopenharmony_ci rect[i].right = scissor[i].maxx; 806bf215546Sopenharmony_ci rect[i].bottom = scissor[i].maxy; 807bf215546Sopenharmony_ci } 808bf215546Sopenharmony_ci 809bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetScissorRects(svga->swc, max_viewports, rect); 810bf215546Sopenharmony_ci } 811bf215546Sopenharmony_ci else { 812bf215546Sopenharmony_ci SVGA3dRect rect; 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_ci rect.x = scissor[0].minx; 815bf215546Sopenharmony_ci rect.y = scissor[0].miny; 816bf215546Sopenharmony_ci rect.w = scissor[0].maxx - scissor[0].minx; /* + 1 ?? */ 817bf215546Sopenharmony_ci rect.h = scissor[0].maxy - scissor[0].miny; /* + 1 ?? */ 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_ci ret = SVGA3D_SetScissorRect(svga->swc, &rect); 820bf215546Sopenharmony_ci } 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci if (ret != PIPE_OK) 823bf215546Sopenharmony_ci return ret; 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci memcpy(svga->state.hw_clear.scissors, scissor, 826bf215546Sopenharmony_ci max_viewports * sizeof *scissor); 827bf215546Sopenharmony_ci } 828bf215546Sopenharmony_ci 829bf215546Sopenharmony_ci return PIPE_OK; 830bf215546Sopenharmony_ci} 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_scissor = 833bf215546Sopenharmony_ci{ 834bf215546Sopenharmony_ci "hw scissor state", 835bf215546Sopenharmony_ci SVGA_NEW_SCISSOR, 836bf215546Sopenharmony_ci emit_scissor_rect 837bf215546Sopenharmony_ci}; 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci/*********************************************************************** 841bf215546Sopenharmony_ci * Userclip state 842bf215546Sopenharmony_ci */ 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_cistatic enum pipe_error 845bf215546Sopenharmony_ciemit_clip_planes( struct svga_context *svga, 846bf215546Sopenharmony_ci uint64_t dirty ) 847bf215546Sopenharmony_ci{ 848bf215546Sopenharmony_ci unsigned i; 849bf215546Sopenharmony_ci enum pipe_error ret; 850bf215546Sopenharmony_ci 851bf215546Sopenharmony_ci /* TODO: just emit directly from svga_set_clip_state()? 852bf215546Sopenharmony_ci */ 853bf215546Sopenharmony_ci for (i = 0; i < SVGA3D_MAX_CLIP_PLANES; i++) { 854bf215546Sopenharmony_ci /* need to express the plane in D3D-style coordinate space. 855bf215546Sopenharmony_ci * GL coords get converted to D3D coords with the matrix: 856bf215546Sopenharmony_ci * [ 1 0 0 0 ] 857bf215546Sopenharmony_ci * [ 0 -1 0 0 ] 858bf215546Sopenharmony_ci * [ 0 0 2 0 ] 859bf215546Sopenharmony_ci * [ 0 0 -1 1 ] 860bf215546Sopenharmony_ci * Apply that matrix to our plane equation, and invert Y. 861bf215546Sopenharmony_ci */ 862bf215546Sopenharmony_ci float a = svga->curr.clip.ucp[i][0]; 863bf215546Sopenharmony_ci float b = svga->curr.clip.ucp[i][1]; 864bf215546Sopenharmony_ci float c = svga->curr.clip.ucp[i][2]; 865bf215546Sopenharmony_ci float d = svga->curr.clip.ucp[i][3]; 866bf215546Sopenharmony_ci float plane[4]; 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ci plane[0] = a; 869bf215546Sopenharmony_ci plane[1] = b; 870bf215546Sopenharmony_ci plane[2] = 2.0f * c; 871bf215546Sopenharmony_ci plane[3] = d - c; 872bf215546Sopenharmony_ci 873bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 874bf215546Sopenharmony_ci //debug_printf("XXX emit DX10 clip plane\n"); 875bf215546Sopenharmony_ci ret = PIPE_OK; 876bf215546Sopenharmony_ci } 877bf215546Sopenharmony_ci else { 878bf215546Sopenharmony_ci ret = SVGA3D_SetClipPlane(svga->swc, i, plane); 879bf215546Sopenharmony_ci if (ret != PIPE_OK) 880bf215546Sopenharmony_ci return ret; 881bf215546Sopenharmony_ci } 882bf215546Sopenharmony_ci } 883bf215546Sopenharmony_ci 884bf215546Sopenharmony_ci return PIPE_OK; 885bf215546Sopenharmony_ci} 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_ci 888bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_clip_planes = 889bf215546Sopenharmony_ci{ 890bf215546Sopenharmony_ci "hw viewport state", 891bf215546Sopenharmony_ci SVGA_NEW_CLIP, 892bf215546Sopenharmony_ci emit_clip_planes 893bf215546Sopenharmony_ci}; 894