svga_screen.c revision b34d138d8453d45f29632d4dcbe040be11265d26
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 "util/u_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 SVGA_MAX_POINTSIZE;
105
106   case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
107      if(!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY, &result))
108         return 4.0;
109      return result.u;
110
111   case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
112      return 16.0;
113
114   case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
115      return 16;
116   case PIPE_CAP_MAX_COMBINED_SAMPLERS:
117      return 16;
118   case PIPE_CAP_NPOT_TEXTURES:
119      return 1;
120   case PIPE_CAP_TWO_SIDED_STENCIL:
121      return 1;
122   case PIPE_CAP_GLSL:
123      return svgascreen->use_ps30 && svgascreen->use_vs30;
124   case PIPE_CAP_ANISOTROPIC_FILTER:
125      return 1;
126   case PIPE_CAP_POINT_SPRITE:
127      return 1;
128   case PIPE_CAP_MAX_RENDER_TARGETS:
129      if(!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_RENDER_TARGETS, &result))
130         return 1;
131      if(!result.u)
132         return 1;
133      return MIN2(result.u, PIPE_MAX_COLOR_BUFS);
134   case PIPE_CAP_OCCLUSION_QUERY:
135      return 1;
136   case PIPE_CAP_TEXTURE_SHADOW_MAP:
137      return 1;
138
139   case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
140      {
141         unsigned levels = SVGA_MAX_TEXTURE_LEVELS;
142         if (sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH, &result))
143            levels = MIN2(util_logbase2(result.u) + 1, levels);
144         else
145            levels = 12 /* 2048x2048 */;
146         if (sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT, &result))
147            levels = MIN2(util_logbase2(result.u) + 1, levels);
148         else
149            levels = 12 /* 2048x2048 */;
150         return levels;
151      }
152
153   case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
154      if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_VOLUME_EXTENT, &result))
155         return 8;  /* max 128x128x128 */
156      return MIN2(util_logbase2(result.u) + 1, SVGA_MAX_TEXTURE_LEVELS);
157
158   case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
159      /*
160       * No mechanism to query the host, and at least limited to 2048x2048 on
161       * certain hardware.
162       */
163      return MIN2(screen->get_paramf(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS),
164                  12.0 /* 2048x2048 */);
165
166   case PIPE_CAP_TEXTURE_MIRROR_REPEAT: /* req. for GL 1.4 */
167      return 1;
168
169   case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */
170      return 1;
171
172   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
173   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
174      return 1;
175   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
176   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
177      return 0;
178
179   default:
180      return 0;
181   }
182}
183
184
185/* This is a fairly pointless interface
186 */
187static int
188svga_get_param(struct pipe_screen *screen, int param)
189{
190   return (int) svga_get_paramf( screen, param );
191}
192
193
194static INLINE SVGA3dDevCapIndex
195svga_translate_format_cap(enum pipe_format format)
196{
197   switch(format) {
198
199   case PIPE_FORMAT_B8G8R8A8_UNORM:
200      return SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8;
201   case PIPE_FORMAT_B8G8R8X8_UNORM:
202      return SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8;
203
204   case PIPE_FORMAT_B5G6R5_UNORM:
205      return SVGA3D_DEVCAP_SURFACEFMT_R5G6B5;
206   case PIPE_FORMAT_B5G5R5A1_UNORM:
207      return SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5;
208   case PIPE_FORMAT_B4G4R4A4_UNORM:
209      return SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4;
210
211   case PIPE_FORMAT_Z16_UNORM:
212      return SVGA3D_DEVCAP_SURFACEFMT_Z_D16;
213   case PIPE_FORMAT_S8Z24_UNORM:
214      return SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8;
215   case PIPE_FORMAT_X8Z24_UNORM:
216      return SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8;
217
218   case PIPE_FORMAT_A8_UNORM:
219      return SVGA3D_DEVCAP_SURFACEFMT_ALPHA8;
220   case PIPE_FORMAT_L8_UNORM:
221      return SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8;
222
223   case PIPE_FORMAT_DXT1_RGB:
224   case PIPE_FORMAT_DXT1_RGBA:
225      return SVGA3D_DEVCAP_SURFACEFMT_DXT1;
226   case PIPE_FORMAT_DXT3_RGBA:
227      return SVGA3D_DEVCAP_SURFACEFMT_DXT3;
228   case PIPE_FORMAT_DXT5_RGBA:
229      return SVGA3D_DEVCAP_SURFACEFMT_DXT5;
230
231   default:
232      return SVGA3D_DEVCAP_MAX;
233   }
234}
235
236
237static boolean
238svga_is_format_supported( struct pipe_screen *screen,
239                          enum pipe_format format,
240                          enum pipe_texture_target target,
241                          unsigned tex_usage,
242                          unsigned geom_flags )
243{
244   struct svga_winsys_screen *sws = svga_screen(screen)->sws;
245   SVGA3dDevCapIndex index;
246   SVGA3dDevCapResult result;
247
248   assert(tex_usage);
249
250   /* Override host capabilities */
251   if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
252      switch(format) {
253
254      /* Often unsupported/problematic. This means we end up with the same
255       * visuals for all virtual hardware implementations.
256       */
257      case PIPE_FORMAT_B4G4R4A4_UNORM:
258      case PIPE_FORMAT_B5G5R5A1_UNORM:
259         return FALSE;
260
261      /* Simulate ability to render into compressed textures */
262      case PIPE_FORMAT_DXT1_RGB:
263      case PIPE_FORMAT_DXT1_RGBA:
264      case PIPE_FORMAT_DXT3_RGBA:
265      case PIPE_FORMAT_DXT5_RGBA:
266         return TRUE;
267
268      default:
269         break;
270      }
271   }
272
273   /* Try to query the host */
274   index = svga_translate_format_cap(format);
275   if( index < SVGA3D_DEVCAP_MAX &&
276       sws->get_cap(sws, index, &result) )
277   {
278      SVGA3dSurfaceFormatCaps mask;
279
280      mask.value = 0;
281      if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
282         mask.offscreenRenderTarget = 1;
283      if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL)
284         mask.zStencil = 1;
285      if (tex_usage & PIPE_TEXTURE_USAGE_SAMPLER)
286         mask.texture = 1;
287
288      if ((result.u & mask.value) == mask.value)
289         return TRUE;
290      else
291         return FALSE;
292   }
293
294   /* Use our translate functions directly rather than relying on a
295    * duplicated list of supported formats which is prone to getting
296    * out of sync:
297    */
298   if(tex_usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DEPTH_STENCIL))
299      return svga_translate_format_render(format) != SVGA3D_FORMAT_INVALID;
300   else
301      return svga_translate_format(format) != SVGA3D_FORMAT_INVALID;
302}
303
304
305static void
306svga_fence_reference(struct pipe_screen *screen,
307                     struct pipe_fence_handle **ptr,
308                     struct pipe_fence_handle *fence)
309{
310   struct svga_winsys_screen *sws = svga_screen(screen)->sws;
311   sws->fence_reference(sws, ptr, fence);
312}
313
314
315static int
316svga_fence_signalled(struct pipe_screen *screen,
317                     struct pipe_fence_handle *fence,
318                     unsigned flag)
319{
320   struct svga_winsys_screen *sws = svga_screen(screen)->sws;
321   return sws->fence_signalled(sws, fence, flag);
322}
323
324
325static int
326svga_fence_finish(struct pipe_screen *screen,
327                  struct pipe_fence_handle *fence,
328                  unsigned flag)
329{
330   struct svga_winsys_screen *sws = svga_screen(screen)->sws;
331
332   SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s fence_ptr %p\n",
333            __FUNCTION__, fence);
334
335   return sws->fence_finish(sws, fence, flag);
336}
337
338
339static void
340svga_destroy_screen( struct pipe_screen *screen )
341{
342   struct svga_screen *svgascreen = svga_screen(screen);
343
344   svga_screen_cache_cleanup(svgascreen);
345
346   pipe_mutex_destroy(svgascreen->swc_mutex);
347   pipe_mutex_destroy(svgascreen->tex_mutex);
348
349   svgascreen->swc->destroy(svgascreen->swc);
350
351   svgascreen->sws->destroy(svgascreen->sws);
352
353   FREE(svgascreen);
354}
355
356
357/**
358 * Create a new svga_screen object
359 */
360struct pipe_screen *
361svga_screen_create(struct svga_winsys_screen *sws)
362{
363   struct svga_screen *svgascreen;
364   struct pipe_screen *screen;
365   SVGA3dDevCapResult result;
366
367#ifdef DEBUG
368   SVGA_DEBUG = debug_get_flags_option("SVGA_DEBUG", svga_debug_flags, 0 );
369#endif
370
371   svgascreen = CALLOC_STRUCT(svga_screen);
372   if (!svgascreen)
373      goto error1;
374
375   svgascreen->debug.force_level_surface_view =
376      debug_get_bool_option("SVGA_FORCE_LEVEL_SURFACE_VIEW", FALSE);
377   svgascreen->debug.force_surface_view =
378      debug_get_bool_option("SVGA_FORCE_SURFACE_VIEW", FALSE);
379   svgascreen->debug.force_sampler_view =
380      debug_get_bool_option("SVGA_FORCE_SAMPLER_VIEW", FALSE);
381   svgascreen->debug.no_surface_view =
382      debug_get_bool_option("SVGA_NO_SURFACE_VIEW", FALSE);
383   svgascreen->debug.no_sampler_view =
384      debug_get_bool_option("SVGA_NO_SAMPLER_VIEW", FALSE);
385
386   screen = &svgascreen->screen;
387
388   screen->destroy = svga_destroy_screen;
389   screen->get_name = svga_get_name;
390   screen->get_vendor = svga_get_vendor;
391   screen->get_param = svga_get_param;
392   screen->get_paramf = svga_get_paramf;
393   screen->is_format_supported = svga_is_format_supported;
394   screen->context_create = svga_context_create;
395   screen->fence_reference = svga_fence_reference;
396   screen->fence_signalled = svga_fence_signalled;
397   screen->fence_finish = svga_fence_finish;
398   svgascreen->sws = sws;
399
400   svga_screen_init_texture_functions(screen);
401   svga_screen_init_buffer_functions(screen);
402
403   svgascreen->use_ps30 =
404      sws->get_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION, &result) &&
405      result.u >= SVGA3DPSVERSION_30 ? TRUE : FALSE;
406
407   svgascreen->use_vs30 =
408      sws->get_cap(sws, SVGA3D_DEVCAP_VERTEX_SHADER_VERSION, &result) &&
409      result.u >= SVGA3DVSVERSION_30 ? TRUE : FALSE;
410
411#if 1
412   /* Shader model 2.0 is unsupported at the moment. */
413   if(!svgascreen->use_ps30 || !svgascreen->use_vs30)
414      goto error2;
415#else
416   if(debug_get_bool_option("SVGA_NO_SM30", FALSE))
417      svgascreen->use_vs30 = svgascreen->use_ps30 = FALSE;
418#endif
419
420   svgascreen->swc = sws->context_create(sws);
421   if(!svgascreen->swc)
422      goto error2;
423
424   pipe_mutex_init(svgascreen->tex_mutex);
425   pipe_mutex_init(svgascreen->swc_mutex);
426
427   svga_screen_cache_init(svgascreen);
428
429   return screen;
430error2:
431   FREE(svgascreen);
432error1:
433   return NULL;
434}
435
436void svga_screen_flush( struct svga_screen *svgascreen,
437                        struct pipe_fence_handle **pfence )
438{
439   struct pipe_fence_handle *fence = NULL;
440
441   SVGA_DBG(DEBUG_PERF, "%s\n", __FUNCTION__);
442
443   pipe_mutex_lock(svgascreen->swc_mutex);
444   svgascreen->swc->flush(svgascreen->swc, &fence);
445   pipe_mutex_unlock(svgascreen->swc_mutex);
446
447   svga_screen_cache_flush(svgascreen, fence);
448
449   if(pfence)
450      *pfence = fence;
451   else
452      svgascreen->sws->fence_reference(svgascreen->sws, &fence, NULL);
453}
454
455struct svga_winsys_screen *
456svga_winsys_screen(struct pipe_screen *screen)
457{
458   return svga_screen(screen)->sws;
459}
460
461#ifdef DEBUG
462struct svga_screen *
463svga_screen(struct pipe_screen *screen)
464{
465   assert(screen);
466   assert(screen->destroy == svga_destroy_screen);
467   return (struct svga_screen *)screen;
468}
469#endif
470