1/**********************************************************
2 * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26#include "util/u_framebuffer.h"
27#include "util/u_inlines.h"
28#include "util/u_pstipple.h"
29
30#include "svga_cmd.h"
31#include "svga_context.h"
32#include "svga_screen.h"
33#include "svga_surface.h"
34#include "svga_resource_texture.h"
35
36
37static void
38svga_set_scissor_states(struct pipe_context *pipe,
39                        unsigned start_slot,
40                        unsigned num_scissors,
41                        const struct pipe_scissor_state *scissors)
42{
43   ASSERTED struct svga_screen *svgascreen = svga_screen(pipe->screen);
44   struct svga_context *svga = svga_context(pipe);
45   unsigned i, num_sc;
46
47   assert(start_slot + num_scissors <= svgascreen->max_viewports);
48
49   for (i = 0, num_sc = start_slot; i < num_scissors; i++)  {
50      svga->curr.scissor[num_sc++] = scissors[i]; /* struct copy */
51   }
52
53   svga->dirty |= SVGA_NEW_SCISSOR;
54}
55
56
57static void
58svga_set_polygon_stipple(struct pipe_context *pipe,
59                         const struct pipe_poly_stipple *stipple)
60{
61   struct svga_context *svga = svga_context(pipe);
62
63   /* release old texture */
64   pipe_resource_reference(&svga->polygon_stipple.texture, NULL);
65
66   /* release old sampler view */
67   if (svga->polygon_stipple.sampler_view) {
68      pipe->sampler_view_destroy(pipe,
69                                 &svga->polygon_stipple.sampler_view->base);
70   }
71
72   /* create new stipple texture */
73   svga->polygon_stipple.texture =
74      util_pstipple_create_stipple_texture(pipe, stipple->stipple);
75
76   /* create new sampler view */
77   svga->polygon_stipple.sampler_view =
78      (struct svga_pipe_sampler_view *)
79      util_pstipple_create_sampler_view(pipe,
80                                        svga->polygon_stipple.texture);
81
82   /* allocate sampler state, if first time */
83   if (!svga->polygon_stipple.sampler) {
84      svga->polygon_stipple.sampler = util_pstipple_create_sampler(pipe);
85   }
86
87   svga->dirty |= SVGA_NEW_STIPPLE;
88}
89
90
91void
92svga_cleanup_framebuffer(struct svga_context *svga)
93{
94   struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
95   struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
96   struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
97   unsigned i;
98
99   for (i = 0; i < svgascreen->max_color_buffers; i++) {
100      pipe_surface_reference(&curr->cbufs[i], NULL);
101      pipe_surface_reference(&hw->cbufs[i], NULL);
102   }
103
104   pipe_surface_reference(&curr->zsbuf, NULL);
105   pipe_surface_reference(&hw->zsbuf, NULL);
106}
107
108
109#define DEPTH_BIAS_SCALE_FACTOR_D16    ((float)(1<<15))
110#define DEPTH_BIAS_SCALE_FACTOR_D24S8  ((float)(1<<23))
111#define DEPTH_BIAS_SCALE_FACTOR_D32    ((float)(1<<31))
112
113
114static void
115svga_set_framebuffer_state(struct pipe_context *pipe,
116                           const struct pipe_framebuffer_state *fb)
117{
118   struct svga_context *svga = svga_context(pipe);
119   struct pipe_framebuffer_state *dst = &svga->curr.framebuffer;
120   unsigned i;
121
122   /* make sure any pending drawing calls are flushed before changing
123    * the framebuffer state
124    */
125   svga_hwtnl_flush_retry(svga);
126
127   dst->width = fb->width;
128   dst->height = fb->height;
129   dst->nr_cbufs = fb->nr_cbufs;
130
131   /* Check that all surfaces are the same size.
132    * Actually, the virtual hardware may support rendertargets with
133    * different size, depending on the host API and driver,
134    */
135   {
136      int width = 0, height = 0;
137      if (fb->zsbuf) {
138         width = fb->zsbuf->width;
139         height = fb->zsbuf->height;
140      }
141      for (i = 0; i < fb->nr_cbufs; ++i) {
142         if (fb->cbufs[i]) {
143            if (width && height) {
144               if (fb->cbufs[i]->width != width ||
145                   fb->cbufs[i]->height != height) {
146                  debug_warning("Mixed-size color and depth/stencil surfaces "
147                                "may not work properly");
148               }
149            }
150            else {
151               width = fb->cbufs[i]->width;
152               height = fb->cbufs[i]->height;
153            }
154         }
155      }
156   }
157
158   util_copy_framebuffer_state(dst, fb);
159
160   if (svga->curr.framebuffer.zsbuf) {
161      switch (svga->curr.framebuffer.zsbuf->format) {
162      case PIPE_FORMAT_Z16_UNORM:
163         svga->curr.depthscale = 1.0f / DEPTH_BIAS_SCALE_FACTOR_D16;
164         break;
165      case PIPE_FORMAT_Z24_UNORM_S8_UINT:
166      case PIPE_FORMAT_Z24X8_UNORM:
167      case PIPE_FORMAT_S8_UINT_Z24_UNORM:
168      case PIPE_FORMAT_X8Z24_UNORM:
169         svga->curr.depthscale = 1.0f / DEPTH_BIAS_SCALE_FACTOR_D24S8;
170         break;
171      case PIPE_FORMAT_Z32_UNORM:
172         svga->curr.depthscale = 1.0f / DEPTH_BIAS_SCALE_FACTOR_D32;
173         break;
174      case PIPE_FORMAT_Z32_FLOAT:
175         svga->curr.depthscale = 1.0f / ((float)(1<<23));
176         break;
177      default:
178         svga->curr.depthscale = 0.0f;
179         break;
180      }
181   }
182   else {
183      svga->curr.depthscale = 0.0f;
184   }
185
186   svga->dirty |= SVGA_NEW_FRAME_BUFFER;
187}
188
189
190static void
191svga_set_clip_state(struct pipe_context *pipe,
192                    const struct pipe_clip_state *clip)
193{
194   struct svga_context *svga = svga_context(pipe);
195
196   svga->curr.clip = *clip; /* struct copy */
197
198   svga->dirty |= SVGA_NEW_CLIP;
199}
200
201
202static void
203svga_set_viewport_states(struct pipe_context *pipe,
204                         unsigned start_slot,
205                         unsigned num_viewports,
206                         const struct pipe_viewport_state *viewports)
207{
208   struct svga_context *svga = svga_context(pipe);
209   ASSERTED struct svga_screen *svgascreen = svga_screen(pipe->screen);
210   unsigned i, num_vp;
211
212   assert(start_slot + num_viewports <= svgascreen->max_viewports);
213
214   for (i = 0, num_vp = start_slot; i < num_viewports; i++)  {
215      svga->curr.viewport[num_vp++] = viewports[i]; /* struct copy */
216   }
217
218   svga->dirty |= SVGA_NEW_VIEWPORT;
219}
220
221
222/**
223 * Called by state tracker to specify a callback function the driver
224 * can use to report info back to the gallium frontend.
225 */
226static void
227svga_set_debug_callback(struct pipe_context *pipe,
228                        const struct util_debug_callback *cb)
229{
230   struct svga_context *svga = svga_context(pipe);
231
232   if (cb) {
233      svga->debug.callback = *cb;
234      svga->swc->debug_callback = &svga->debug.callback;
235   } else {
236      memset(&svga->debug.callback, 0, sizeof(svga->debug.callback));
237      svga->swc->debug_callback = NULL;
238   }
239}
240
241
242void
243svga_init_misc_functions(struct svga_context *svga)
244{
245   svga->pipe.set_scissor_states = svga_set_scissor_states;
246   svga->pipe.set_polygon_stipple = svga_set_polygon_stipple;
247   svga->pipe.set_framebuffer_state = svga_set_framebuffer_state;
248   svga->pipe.set_clip_state = svga_set_clip_state;
249   svga->pipe.set_viewport_states = svga_set_viewport_states;
250   svga->pipe.set_debug_callback = svga_set_debug_callback;
251}
252