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