svga_screen.c revision 6c403750d6515f8b2f333d995c87676016e1883d
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_memory.h"
27#include "pipe/p_inlines.h"
28#include "util/u_string.h"
29#include "util/u_math.h"
30
31#include "svga_winsys.h"
32#include "svga_context.h"
33#include "svga_screen.h"
34#include "svga_screen_texture.h"
35#include "svga_screen_buffer.h"
36#include "svga_debug.h"
37
38#include "svga3d_shaderdefs.h"
39
40
41#ifdef DEBUG
42int SVGA_DEBUG = 0;
43
44static const struct debug_named_value svga_debug_flags[] = {
45   { "dma",      DEBUG_DMA },
46   { "tgsi",     DEBUG_TGSI },
47   { "pipe",     DEBUG_PIPE },
48   { "state",    DEBUG_STATE },
49   { "screen",   DEBUG_SCREEN },
50   { "tex",      DEBUG_TEX },
51   { "swtnl",    DEBUG_SWTNL },
52   { "const",    DEBUG_CONSTS },
53   { "viewport", DEBUG_VIEWPORT },
54   { "views",    DEBUG_VIEWS },
55   { "perf",     DEBUG_PERF },
56   { "flush",    DEBUG_FLUSH },
57   { "sync",     DEBUG_SYNC },
58   { "cache",    DEBUG_CACHE },
59   {NULL, 0}
60};
61#endif
62
63static const char *
64svga_get_vendor( struct pipe_screen *pscreen )
65{
66   return "VMware, Inc.";
67}
68
69
70static const char *
71svga_get_name( struct pipe_screen *pscreen )
72{
73#ifdef DEBUG
74   /* Only return internal details in the DEBUG version:
75    */
76   return "SVGA3D; build: DEBUG; mutex: " PIPE_ATOMIC;
77#else
78   return "SVGA3D; build: RELEASE; ";
79#endif
80}
81
82
83
84
85static float
86svga_get_paramf(struct pipe_screen *screen, int param)
87{
88   struct svga_screen *svgascreen = svga_screen(screen);
89   struct svga_winsys_screen *sws = svgascreen->sws;
90   SVGA3dDevCapResult result;
91
92   switch (param) {
93   case PIPE_CAP_MAX_LINE_WIDTH:
94      /* fall-through */
95   case PIPE_CAP_MAX_LINE_WIDTH_AA:
96      return 7.0;
97
98   case PIPE_CAP_MAX_POINT_WIDTH:
99      /* fall-through */
100   case PIPE_CAP_MAX_POINT_WIDTH_AA:
101      /* Keep this to a reasonable size to avoid failures in
102       * conform/pntaa.c:
103       */
104      return 80.0;
105
106   case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
107      return 4.0;
108
109   case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
110      return 16.0;
111
112   case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
113      return 16;
114   case PIPE_CAP_NPOT_TEXTURES:
115      return 1;
116   case PIPE_CAP_TWO_SIDED_STENCIL:
117      return 1;
118   case PIPE_CAP_GLSL:
119      return svgascreen->use_ps30 && svgascreen->use_vs30;
120   case PIPE_CAP_ANISOTROPIC_FILTER:
121      return 1;
122   case PIPE_CAP_POINT_SPRITE:
123      return 1;
124   case PIPE_CAP_MAX_RENDER_TARGETS:
125      if(!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_RENDER_TARGETS, &result))
126         return 1;
127      if(!result.u)
128         return 1;
129      return MIN2(result.u, PIPE_MAX_COLOR_BUFS);
130   case PIPE_CAP_OCCLUSION_QUERY:
131      return 1;
132   case PIPE_CAP_TEXTURE_SHADOW_MAP:
133      return 1;
134   case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
135      return SVGA_MAX_TEXTURE_LEVELS;
136   case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
137      return 8;  /* max 128x128x128 */
138   case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
139      return SVGA_MAX_TEXTURE_LEVELS;
140
141   case PIPE_CAP_TEXTURE_MIRROR_REPEAT: /* req. for GL 1.4 */
142      return 1;
143
144   case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */
145      return 1;
146
147   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
148   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
149      return 1;
150   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
151   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
152      return 0;
153
154   default:
155      return 0;
156   }
157}
158
159
160/* This is a fairly pointless interface
161 */
162static int
163svga_get_param(struct pipe_screen *screen, int param)
164{
165   return (int) svga_get_paramf( screen, param );
166}
167
168
169static INLINE SVGA3dDevCapIndex
170svga_translate_format_cap(enum pipe_format format)
171{
172   switch(format) {
173
174   case PIPE_FORMAT_A8R8G8B8_UNORM:
175      return SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8;
176   case PIPE_FORMAT_X8R8G8B8_UNORM:
177      return SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8;
178
179   case PIPE_FORMAT_R5G6B5_UNORM:
180      return SVGA3D_DEVCAP_SURFACEFMT_R5G6B5;
181   case PIPE_FORMAT_A1R5G5B5_UNORM:
182      return SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5;
183   case PIPE_FORMAT_A4R4G4B4_UNORM:
184      return SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4;
185
186   case PIPE_FORMAT_Z16_UNORM:
187      return SVGA3D_DEVCAP_SURFACEFMT_Z_D16;
188   case PIPE_FORMAT_Z24S8_UNORM:
189      return SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8;
190   case PIPE_FORMAT_Z24X8_UNORM:
191      return SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8;
192
193   case PIPE_FORMAT_A8_UNORM:
194      return SVGA3D_DEVCAP_SURFACEFMT_ALPHA8;
195   case PIPE_FORMAT_L8_UNORM:
196      return SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8;
197
198   case PIPE_FORMAT_DXT1_RGB:
199   case PIPE_FORMAT_DXT1_RGBA:
200      return SVGA3D_DEVCAP_SURFACEFMT_DXT1;
201   case PIPE_FORMAT_DXT3_RGBA:
202      return SVGA3D_DEVCAP_SURFACEFMT_DXT3;
203   case PIPE_FORMAT_DXT5_RGBA:
204      return SVGA3D_DEVCAP_SURFACEFMT_DXT5;
205
206   default:
207      return SVGA3D_DEVCAP_MAX;
208   }
209}
210
211
212static boolean
213svga_is_format_supported( struct pipe_screen *screen,
214                          enum pipe_format format,
215                          enum pipe_texture_target target,
216                          unsigned tex_usage,
217                          unsigned geom_flags )
218{
219   struct svga_winsys_screen *sws = svga_screen(screen)->sws;
220   SVGA3dDevCapIndex index;
221   SVGA3dDevCapResult result;
222
223   assert(tex_usage);
224
225   /* Override host capabilities */
226   if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
227      switch(format) {
228
229      /* Often unsupported/problematic. This means we end up with the same
230       * visuals for all virtual hardware implementations.
231       */
232      case PIPE_FORMAT_A4R4G4B4_UNORM:
233      case PIPE_FORMAT_A1R5G5B5_UNORM:
234         return FALSE;
235
236      /* Simulate ability to render into compressed textures */
237      case PIPE_FORMAT_DXT1_RGB:
238      case PIPE_FORMAT_DXT1_RGBA:
239      case PIPE_FORMAT_DXT3_RGBA:
240      case PIPE_FORMAT_DXT5_RGBA:
241         return TRUE;
242
243      default:
244         break;
245      }
246   }
247
248   /* Try to query the host */
249   index = svga_translate_format_cap(format);
250   if( index < SVGA3D_DEVCAP_MAX &&
251       sws->get_cap(sws, index, &result) )
252   {
253      SVGA3dSurfaceFormatCaps mask;
254
255      mask.value = 0;
256      if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
257         mask.offscreenRenderTarget = 1;
258      if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL)
259         mask.zStencil = 1;
260      if (tex_usage & PIPE_TEXTURE_USAGE_SAMPLER)
261         mask.texture = 1;
262
263      if ((result.u & mask.value) == mask.value)
264         return TRUE;
265      else
266         return FALSE;
267   }
268
269   /* Use our translate functions directly rather than relying on a
270    * duplicated list of supported formats which is prone to getting
271    * out of sync:
272    */
273   if(tex_usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DEPTH_STENCIL))
274      return svga_translate_format_render(format) != SVGA3D_FORMAT_INVALID;
275   else
276      return svga_translate_format(format) != SVGA3D_FORMAT_INVALID;
277}
278
279
280static void
281svga_fence_reference(struct pipe_screen *screen,
282                     struct pipe_fence_handle **ptr,
283                     struct pipe_fence_handle *fence)
284{
285   struct svga_winsys_screen *sws = svga_screen(screen)->sws;
286   sws->fence_reference(sws, ptr, fence);
287}
288
289
290static int
291svga_fence_signalled(struct pipe_screen *screen,
292                     struct pipe_fence_handle *fence,
293                     unsigned flag)
294{
295   struct svga_winsys_screen *sws = svga_screen(screen)->sws;
296   return sws->fence_signalled(sws, fence, flag);
297}
298
299
300static int
301svga_fence_finish(struct pipe_screen *screen,
302                  struct pipe_fence_handle *fence,
303                  unsigned flag)
304{
305   struct svga_winsys_screen *sws = svga_screen(screen)->sws;
306
307   SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s fence_ptr %p\n",
308            __FUNCTION__, fence);
309
310   return sws->fence_finish(sws, fence, flag);
311}
312
313
314static void
315svga_destroy_screen( struct pipe_screen *screen )
316{
317   struct svga_screen *svgascreen = svga_screen(screen);
318
319   svga_screen_cache_cleanup(svgascreen);
320
321   pipe_mutex_destroy(svgascreen->swc_mutex);
322   pipe_mutex_destroy(svgascreen->tex_mutex);
323
324   svgascreen->swc->destroy(svgascreen->swc);
325
326   svgascreen->sws->destroy(svgascreen->sws);
327
328   FREE(svgascreen);
329}
330
331
332/**
333 * Create a new svga_screen object
334 */
335struct pipe_screen *
336svga_screen_create(struct svga_winsys_screen *sws)
337{
338   struct svga_screen *svgascreen;
339   struct pipe_screen *screen;
340   SVGA3dDevCapResult result;
341
342#ifdef DEBUG
343   SVGA_DEBUG = debug_get_flags_option("SVGA_DEBUG", svga_debug_flags, 0 );
344#endif
345
346   svgascreen = CALLOC_STRUCT(svga_screen);
347   if (!svgascreen)
348      goto error1;
349
350   svgascreen->debug.force_level_surface_view =
351      debug_get_bool_option("SVGA_FORCE_LEVEL_SURFACE_VIEW", FALSE);
352   svgascreen->debug.force_surface_view =
353      debug_get_bool_option("SVGA_FORCE_SURFACE_VIEW", FALSE);
354   svgascreen->debug.force_sampler_view =
355      debug_get_bool_option("SVGA_FORCE_SAMPLER_VIEW", FALSE);
356   svgascreen->debug.no_surface_view =
357      debug_get_bool_option("SVGA_NO_SURFACE_VIEW", FALSE);
358   svgascreen->debug.no_sampler_view =
359      debug_get_bool_option("SVGA_NO_SAMPLER_VIEW", FALSE);
360
361   screen = &svgascreen->screen;
362
363   screen->destroy = svga_destroy_screen;
364   screen->get_name = svga_get_name;
365   screen->get_vendor = svga_get_vendor;
366   screen->get_param = svga_get_param;
367   screen->get_paramf = svga_get_paramf;
368   screen->is_format_supported = svga_is_format_supported;
369   screen->fence_reference = svga_fence_reference;
370   screen->fence_signalled = svga_fence_signalled;
371   screen->fence_finish = svga_fence_finish;
372   svgascreen->sws = sws;
373
374   svga_screen_init_texture_functions(screen);
375   svga_screen_init_buffer_functions(screen);
376
377   svgascreen->use_ps30 =
378      sws->get_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION, &result) &&
379      result.u >= SVGA3DPSVERSION_30 ? TRUE : FALSE;
380
381   svgascreen->use_vs30 =
382      sws->get_cap(sws, SVGA3D_DEVCAP_VERTEX_SHADER_VERSION, &result) &&
383      result.u >= SVGA3DVSVERSION_30 ? TRUE : FALSE;
384
385#if 1
386   /* Shader model 2.0 is unsupported at the moment. */
387   if(!svgascreen->use_ps30 || !svgascreen->use_vs30)
388      goto error2;
389#else
390   if(debug_get_bool_option("SVGA_NO_SM30", FALSE))
391      svgascreen->use_vs30 = svgascreen->use_ps30 = FALSE;
392#endif
393
394   svgascreen->swc = sws->context_create(sws);
395   if(!svgascreen->swc)
396      goto error2;
397
398   pipe_mutex_init(svgascreen->tex_mutex);
399   pipe_mutex_init(svgascreen->swc_mutex);
400
401   svga_screen_cache_init(svgascreen);
402
403   return screen;
404error2:
405   FREE(svgascreen);
406error1:
407   return NULL;
408}
409
410void svga_screen_flush( struct svga_screen *svgascreen,
411                        struct pipe_fence_handle **pfence )
412{
413   struct pipe_fence_handle *fence = NULL;
414
415   SVGA_DBG(DEBUG_PERF, "%s\n", __FUNCTION__);
416
417   pipe_mutex_lock(svgascreen->swc_mutex);
418   svgascreen->swc->flush(svgascreen->swc, &fence);
419   pipe_mutex_unlock(svgascreen->swc_mutex);
420
421   svga_screen_cache_flush(svgascreen, fence);
422
423   if(pfence)
424      *pfence = fence;
425   else
426      svgascreen->sws->fence_reference(svgascreen->sws, &fence, NULL);
427}
428
429struct svga_winsys_screen *
430svga_winsys_screen(struct pipe_screen *screen)
431{
432   return svga_screen(screen)->sws;
433}
434
435#ifdef DEBUG
436struct svga_screen *
437svga_screen(struct pipe_screen *screen)
438{
439   assert(screen);
440   assert(screen->destroy == svga_destroy_screen);
441   return (struct svga_screen *)screen;
442}
443#endif
444