virgl_screen.c 21.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * Copyright 2014, 2015 Red Hat.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 * license, and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_format_s3tc.h"
#include "util/u_video.h"
27
#include "util/os_time.h"
28 29 30 31 32
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"

#include "tgsi/tgsi_exec.h"

33
#include "virgl_screen.h"
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
#include "virgl_resource.h"
#include "virgl_public.h"
#include "virgl_context.h"

#define SP_MAX_TEXTURE_2D_LEVELS 15  /* 16K x 16K */
#define SP_MAX_TEXTURE_3D_LEVELS 9   /* 512 x 512 x 512 */
#define SP_MAX_TEXTURE_CUBE_LEVELS 13  /* 4K x 4K */

static const char *
virgl_get_vendor(struct pipe_screen *screen)
{
   return "Red Hat";
}


static const char *
virgl_get_name(struct pipe_screen *screen)
{
   return "virgl";
}

static int
virgl_get_param(struct pipe_screen *screen, enum pipe_cap param)
{
   struct virgl_screen *vscreen = virgl_screen(screen);
   switch (param) {
   case PIPE_CAP_NPOT_TEXTURES:
      return 1;
   case PIPE_CAP_SM3:
      return 1;
   case PIPE_CAP_ANISOTROPIC_FILTER:
      return 1;
   case PIPE_CAP_POINT_SPRITE:
      return 1;
   case PIPE_CAP_MAX_RENDER_TARGETS:
      return vscreen->caps.caps.v1.max_render_targets;
   case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
      return vscreen->caps.caps.v1.max_dual_source_render_targets;
   case PIPE_CAP_OCCLUSION_QUERY:
      return vscreen->caps.caps.v1.bset.occlusion_query;
   case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
      return vscreen->caps.caps.v1.bset.mirror_clamp;
   case PIPE_CAP_TEXTURE_SWIZZLE:
      return 1;
   case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
      return SP_MAX_TEXTURE_2D_LEVELS;
   case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
      return SP_MAX_TEXTURE_3D_LEVELS;
   case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
      return SP_MAX_TEXTURE_CUBE_LEVELS;
   case PIPE_CAP_BLEND_EQUATION_SEPARATE:
      return 1;
   case PIPE_CAP_INDEP_BLEND_ENABLE:
      return vscreen->caps.caps.v1.bset.indep_blend_enable;
   case PIPE_CAP_INDEP_BLEND_FUNC:
      return vscreen->caps.caps.v1.bset.indep_blend_func;
   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
      return vscreen->caps.caps.v1.bset.fragment_coord_conventions;
   case PIPE_CAP_DEPTH_CLIP_DISABLE:
      return vscreen->caps.caps.v1.bset.depth_clip_disable;
   case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
      return vscreen->caps.caps.v1.max_streamout_buffers;
   case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
   case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
      return 16*4;
   case PIPE_CAP_PRIMITIVE_RESTART:
      return vscreen->caps.caps.v1.bset.primitive_restart;
   case PIPE_CAP_SHADER_STENCIL_EXPORT:
      return vscreen->caps.caps.v1.bset.shader_stencil_export;
   case PIPE_CAP_TGSI_INSTANCEID:
   case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
      return 1;
   case PIPE_CAP_SEAMLESS_CUBE_MAP:
      return vscreen->caps.caps.v1.bset.seamless_cube_map;
   case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
      return vscreen->caps.caps.v1.bset.seamless_cube_map_per_texture;
   case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
      return vscreen->caps.caps.v1.max_texture_array_layers;
   case PIPE_CAP_MIN_TEXEL_OFFSET:
116
      return vscreen->caps.caps.v2.min_texel_offset;
117
   case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
118
      return vscreen->caps.caps.v2.min_texture_gather_offset;
119
   case PIPE_CAP_MAX_TEXEL_OFFSET:
120
      return vscreen->caps.caps.v2.max_texel_offset;
121
   case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
122
      return vscreen->caps.caps.v2.max_texture_gather_offset;
123 124 125 126 127 128 129 130 131 132 133 134 135
   case PIPE_CAP_CONDITIONAL_RENDER:
      return vscreen->caps.caps.v1.bset.conditional_render;
   case PIPE_CAP_TEXTURE_BARRIER:
      return 0;
   case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
      return 1;
   case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
   case PIPE_CAP_VERTEX_COLOR_CLAMPED:
      return vscreen->caps.caps.v1.bset.color_clamping;
   case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
      return 1;
   case PIPE_CAP_GLSL_FEATURE_LEVEL:
      return vscreen->caps.caps.v1.glsl_level;
136 137
   case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
      return MIN2(vscreen->caps.caps.v1.glsl_level, 140);
138 139 140 141 142 143 144
   case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
      return 0;
   case PIPE_CAP_COMPUTE:
      return 0;
   case PIPE_CAP_USER_VERTEX_BUFFERS:
      return 0;
   case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
145
      return vscreen->caps.caps.v2.uniform_buffer_offset_alignment;
146
   case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
147
   case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
      return vscreen->caps.caps.v1.bset.streamout_pause_resume;
   case PIPE_CAP_START_INSTANCE:
      return vscreen->caps.caps.v1.bset.start_instance;
   case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
   case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
   case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
   case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
   case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
      return 0;
   case PIPE_CAP_QUERY_TIMESTAMP:
      return 1;
   case PIPE_CAP_QUERY_TIME_ELAPSED:
      return 0;
   case PIPE_CAP_TGSI_TEXCOORD:
      return 0;
   case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
      return VIRGL_MAP_BUFFER_ALIGNMENT;
   case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
      return vscreen->caps.caps.v1.max_tbo_size > 0;
   case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
168
      return vscreen->caps.caps.v2.texture_buffer_offset_alignment;
169 170
   case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY:
      return 0;
171 172 173 174 175 176 177 178 179 180 181 182 183
   case PIPE_CAP_CUBE_MAP_ARRAY:
      return vscreen->caps.caps.v1.bset.cube_map_array;
   case PIPE_CAP_TEXTURE_MULTISAMPLE:
      return vscreen->caps.caps.v1.bset.texture_multisample;
   case PIPE_CAP_MAX_VIEWPORTS:
      return vscreen->caps.caps.v1.max_viewports;
   case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
      return vscreen->caps.caps.v1.max_tbo_size;
   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
   case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
   case PIPE_CAP_ENDIANNESS:
      return 0;
   case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
184
   case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
185 186 187 188
      return 1;
   case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT:
      return 0;
   case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
189
      return vscreen->caps.caps.v2.max_geom_output_vertices;
190
   case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
191
      return vscreen->caps.caps.v2.max_geom_total_output_components;
192 193 194 195
   case PIPE_CAP_TEXTURE_QUERY_LOD:
      return vscreen->caps.caps.v1.bset.texture_query_lod;
   case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
      return vscreen->caps.caps.v1.max_texture_gather_components;
196 197
   case PIPE_CAP_DRAW_INDIRECT:
      return vscreen->caps.caps.v1.bset.has_indirect_draw;
198 199 200
   case PIPE_CAP_SAMPLE_SHADING:
   case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
      return vscreen->caps.caps.v1.bset.has_sample_shading;
201 202
   case PIPE_CAP_CULL_DISTANCE:
      return vscreen->caps.caps.v1.bset.has_cull;
203 204
   case PIPE_CAP_MAX_VERTEX_STREAMS:
      return vscreen->caps.caps.v1.glsl_level >= 400 ? 4 : 1;
205 206
   case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
      return vscreen->caps.caps.v1.bset.conditional_render_inverted;
207 208
   case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE:
      return vscreen->caps.caps.v1.bset.derivative_control;
209 210 211 212 213
   case PIPE_CAP_TEXTURE_GATHER_SM5:
   case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
   case PIPE_CAP_FAKE_SW_MSAA:
   case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
   case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
214 215
   case PIPE_CAP_MULTI_DRAW_INDIRECT:
   case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
216 217 218 219 220 221 222 223 224 225 226 227 228 229
   case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
   case PIPE_CAP_SAMPLER_VIEW_TARGET:
   case PIPE_CAP_CLIP_HALFZ:
   case PIPE_CAP_VERTEXID_NOBASE:
   case PIPE_CAP_POLYGON_OFFSET_CLAMP:
   case PIPE_CAP_MULTISAMPLE_Z_RESOLVE:
   case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
   case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
   case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
   case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
   case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
   case PIPE_CAP_DEPTH_BOUNDS_TEST:
   case PIPE_CAP_TGSI_TXQS:
   case PIPE_CAP_SHAREABLE_SHADERS:
230
   case PIPE_CAP_CLEAR_TEXTURE:
231
   case PIPE_CAP_DRAW_PARAMETERS:
232
   case PIPE_CAP_TGSI_PACK_HALF_FLOAT:
233 234
   case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
   case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
235
   case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
236
   case PIPE_CAP_INVALIDATE_BUFFER:
237
   case PIPE_CAP_GENERATE_MIPMAP:
238
   case PIPE_CAP_SURFACE_REINTERPRET_BLOCKS:
239
   case PIPE_CAP_QUERY_BUFFER_OBJECT:
240 241 242
   case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
   case PIPE_CAP_STRING_MARKER:
   case PIPE_CAP_QUERY_MEMORY_INFO:
243 244 245 246
   case PIPE_CAP_PCI_GROUP:
   case PIPE_CAP_PCI_BUS:
   case PIPE_CAP_PCI_DEVICE:
   case PIPE_CAP_PCI_FUNCTION:
247
   case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
248
   case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR:
249
   case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES:
250
   case PIPE_CAP_TGSI_VOTE:
251
   case PIPE_CAP_MAX_WINDOW_RECTANGLES:
252
   case PIPE_CAP_POLYGON_OFFSET_UNITS_UNSCALED:
253
   case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:
254
   case PIPE_CAP_TGSI_ARRAY_COMPONENTS:
255
   case PIPE_CAP_TGSI_CAN_READ_OUTPUTS:
256
   case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
257
   case PIPE_CAP_TGSI_FS_FBFETCH:
258
   case PIPE_CAP_TGSI_MUL_ZERO_WINS:
259
   case PIPE_CAP_INT64:
260
   case PIPE_CAP_INT64_DIVMOD:
261
   case PIPE_CAP_TGSI_TEX_TXF_LZ:
262
   case PIPE_CAP_TGSI_CLOCK:
263
   case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE:
264
   case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:
265
   case PIPE_CAP_TGSI_BALLOT:
266
   case PIPE_CAP_DOUBLES:
267
   case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
268
   case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
269
   case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
270
   case PIPE_CAP_POST_DEPTH_COVERAGE:
271
   case PIPE_CAP_BINDLESS_TEXTURE:
272
   case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:
273
   case PIPE_CAP_QUERY_SO_OVERFLOW:
274
   case PIPE_CAP_MEMOBJ:
275
   case PIPE_CAP_LOAD_CONSTBUF:
276
   case PIPE_CAP_TGSI_ANY_REG_AS_ADDRESS:
277
   case PIPE_CAP_TILE_RASTER_ORDER:
278
   case PIPE_CAP_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
279
   case PIPE_CAP_SIGNED_VERTEX_BUFFER_OFFSET:
280
   case PIPE_CAP_CONTEXT_PRIORITY_MASK:
281
   case PIPE_CAP_FENCE_SIGNAL:
282
   case PIPE_CAP_CONSTBUF0_FLAGS:
283
   case PIPE_CAP_PACKED_UNIFORMS:
284 285 286 287 288 289
   case PIPE_CAP_CONSERVATIVE_RASTER_POST_SNAP_TRIANGLES:
   case PIPE_CAP_CONSERVATIVE_RASTER_POST_SNAP_POINTS_LINES:
   case PIPE_CAP_CONSERVATIVE_RASTER_PRE_SNAP_TRIANGLES:
   case PIPE_CAP_CONSERVATIVE_RASTER_PRE_SNAP_POINTS_LINES:
   case PIPE_CAP_CONSERVATIVE_RASTER_POST_DEPTH_COVERAGE:
   case PIPE_CAP_MAX_CONSERVATIVE_RASTER_SUBPIXEL_PRECISION_BIAS:
290 291 292 293 294 295 296 297 298 299
      return 0;
   case PIPE_CAP_VENDOR_ID:
      return 0x1af4;
   case PIPE_CAP_DEVICE_ID:
      return 0x1010;
   case PIPE_CAP_ACCELERATED:
      return 1;
   case PIPE_CAP_UMA:
   case PIPE_CAP_VIDEO_MEMORY:
      return 0;
300 301
   case PIPE_CAP_NATIVE_FENCE_FD:
      return 0;
302 303 304 305 306 307 308
   }
   /* should only get here on unhandled cases */
   debug_printf("Unexpected PIPE_CAP %d query\n", param);
   return 0;
}

static int
309 310 311
virgl_get_shader_param(struct pipe_screen *screen,
                       enum pipe_shader_type shader,
                       enum pipe_shader_cap param)
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
{
   struct virgl_screen *vscreen = virgl_screen(screen);
   switch(shader)
   {
   case PIPE_SHADER_FRAGMENT:
   case PIPE_SHADER_VERTEX:
   case PIPE_SHADER_GEOMETRY:
      switch (param) {
      case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
      case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
      case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
      case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
         return INT_MAX;
      case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
      case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
      case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
         return 1;
      case PIPE_SHADER_CAP_MAX_INPUTS:
         if (vscreen->caps.caps.v1.glsl_level < 150)
331
            return vscreen->caps.caps.v2.max_vertex_attribs;
332
         return (shader == PIPE_SHADER_VERTEX ||
333
                 shader == PIPE_SHADER_GEOMETRY) ? vscreen->caps.caps.v2.max_vertex_attribs : 32;
334
      case PIPE_SHADER_CAP_MAX_OUTPUTS:
335 336 337
         if (shader == PIPE_SHADER_FRAGMENT)
            return vscreen->caps.caps.v1.max_render_targets;
         return vscreen->caps.caps.v2.max_vertex_outputs;
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
     // case PIPE_SHADER_CAP_MAX_CONSTS:
     //    return 4096;
      case PIPE_SHADER_CAP_MAX_TEMPS:
         return 256;
      case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
         return vscreen->caps.caps.v1.max_uniform_blocks;
    //  case PIPE_SHADER_CAP_MAX_ADDRS:
     //    return 1;
      case PIPE_SHADER_CAP_SUBROUTINES:
         return 1;
      case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
            return 16;
      case PIPE_SHADER_CAP_INTEGERS:
         return vscreen->caps.caps.v1.glsl_level >= 130;
      case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
         return 32;
      case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
         return 4096 * sizeof(float[4]);
356
      case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
357
      case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
358
      case PIPE_SHADER_CAP_INT64_ATOMICS:
Jan Vesely's avatar
Jan Vesely committed
359
      case PIPE_SHADER_CAP_FP16:
360 361
      case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
      case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
362 363 364 365 366 367 368 369 370 371 372
      default:
         return 0;
      }
   default:
      return 0;
   }
}

static float
virgl_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
{
373
   struct virgl_screen *vscreen = virgl_screen(screen);
374 375
   switch (param) {
   case PIPE_CAPF_MAX_LINE_WIDTH:
376
      return vscreen->caps.caps.v2.max_aliased_line_width;
377
   case PIPE_CAPF_MAX_LINE_WIDTH_AA:
378
      return vscreen->caps.caps.v2.max_smooth_line_width;
379
   case PIPE_CAPF_MAX_POINT_WIDTH:
380
      return vscreen->caps.caps.v2.max_aliased_point_size;
381
   case PIPE_CAPF_MAX_POINT_WIDTH_AA:
382
      return vscreen->caps.caps.v2.max_smooth_point_size;
383 384 385
   case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
      return 16.0;
   case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
386
      return vscreen->caps.caps.v2.max_texture_lod_bias;
387 388 389 390
   case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
   case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
   case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
      return 0.0f;
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
   }
   /* should only get here on unhandled cases */
   debug_printf("Unexpected PIPE_CAPF %d query\n", param);
   return 0.0;
}

static boolean
virgl_is_vertex_format_supported(struct pipe_screen *screen,
                                 enum pipe_format format)
{
   struct virgl_screen *vscreen = virgl_screen(screen);
   const struct util_format_description *format_desc;
   int i;

   format_desc = util_format_description(format);
   if (!format_desc)
      return FALSE;

   if (format == PIPE_FORMAT_R11G11B10_FLOAT) {
      int vformat = VIRGL_FORMAT_R11G11B10_FLOAT;
      int big = vformat / 32;
      int small = vformat % 32;
      if (!(vscreen->caps.caps.v1.vertexbuffer.bitmask[big] & (1 << small)))
         return FALSE;
      return TRUE;
   }

   /* Find the first non-VOID channel. */
   for (i = 0; i < 4; i++) {
      if (format_desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
         break;
      }
   }

   if (i == 4)
      return FALSE;

   if (format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN)
      return FALSE;

   if (format_desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED)
      return FALSE;
   return TRUE;
}

/**
 * Query format support for creating a texture, drawing surface, etc.
 * \param format  the format to test
 * \param type  one of PIPE_TEXTURE, PIPE_SURFACE
 */
static boolean
virgl_is_format_supported( struct pipe_screen *screen,
                                 enum pipe_format format,
                                 enum pipe_texture_target target,
                                 unsigned sample_count,
                                 unsigned bind)
{
   struct virgl_screen *vscreen = virgl_screen(screen);
   const struct util_format_description *format_desc;
   int i;

   assert(target == PIPE_BUFFER ||
          target == PIPE_TEXTURE_1D ||
          target == PIPE_TEXTURE_1D_ARRAY ||
          target == PIPE_TEXTURE_2D ||
          target == PIPE_TEXTURE_2D_ARRAY ||
          target == PIPE_TEXTURE_RECT ||
          target == PIPE_TEXTURE_3D ||
          target == PIPE_TEXTURE_CUBE ||
          target == PIPE_TEXTURE_CUBE_ARRAY);

   format_desc = util_format_description(format);
   if (!format_desc)
      return FALSE;

   if (util_format_is_intensity(format))
      return FALSE;

   if (sample_count > 1) {
      if (!vscreen->caps.caps.v1.bset.texture_multisample)
         return FALSE;
      if (sample_count > vscreen->caps.caps.v1.max_samples)
         return FALSE;
   }

   if (bind & PIPE_BIND_VERTEX_BUFFER) {
      return virgl_is_vertex_format_supported(screen, format);
   }

   if (bind & PIPE_BIND_RENDER_TARGET) {
      if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
         return FALSE;

      /*
       * Although possible, it is unnatural to render into compressed or YUV
       * surfaces. So disable these here to avoid going into weird paths
       * inside the state trackers.
       */
      if (format_desc->block.width != 1 ||
          format_desc->block.height != 1)
         return FALSE;

      {
         int big = format / 32;
         int small = format % 32;
         if (!(vscreen->caps.caps.v1.render.bitmask[big] & (1 << small)))
            return FALSE;
      }
   }

   if (bind & PIPE_BIND_DEPTH_STENCIL) {
      if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
         return FALSE;
   }

   /*
    * All other operations (sampling, transfer, etc).
    */

   if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
511
      goto out_lookup;
512 513 514 515
   }
   if (format_desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
      goto out_lookup;
   }
Dave Airlie's avatar
Dave Airlie committed
516 517 518
   if (format_desc->layout == UTIL_FORMAT_LAYOUT_BPTC) {
      goto out_lookup;
   }
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559

   if (format == PIPE_FORMAT_R11G11B10_FLOAT) {
      goto out_lookup;
   } else if (format == PIPE_FORMAT_R9G9B9E5_FLOAT) {
      goto out_lookup;
   }

   /* Find the first non-VOID channel. */
   for (i = 0; i < 4; i++) {
      if (format_desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
         break;
      }
   }

   if (i == 4)
      return FALSE;

   /* no L4A4 */
   if (format_desc->nr_channels < 4 && format_desc->channel[i].size == 4)
      return FALSE;

 out_lookup:
   {
      int big = format / 32;
      int small = format % 32;
      if (!(vscreen->caps.caps.v1.sampler.bitmask[big] & (1 << small)))
         return FALSE;
   }
   /*
    * Everything else should be supported by u_format.
    */
   return TRUE;
}

static void virgl_flush_frontbuffer(struct pipe_screen *screen,
                                      struct pipe_resource *res,
                                      unsigned level, unsigned layer,
                                    void *winsys_drawable_handle, struct pipe_box *sub_box)
{
   struct virgl_screen *vscreen = virgl_screen(screen);
   struct virgl_winsys *vws = vscreen->vws;
560
   struct virgl_resource *vres = virgl_resource(res);
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577

   if (vws->flush_frontbuffer)
      vws->flush_frontbuffer(vws, vres->hw_res, level, layer, winsys_drawable_handle,
                             sub_box);
}

static void virgl_fence_reference(struct pipe_screen *screen,
                                  struct pipe_fence_handle **ptr,
                                  struct pipe_fence_handle *fence)
{
   struct virgl_screen *vscreen = virgl_screen(screen);
   struct virgl_winsys *vws = vscreen->vws;

   vws->fence_reference(vws, ptr, fence);
}

static boolean virgl_fence_finish(struct pipe_screen *screen,
578
                                  struct pipe_context *ctx,
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
                                  struct pipe_fence_handle *fence,
                                  uint64_t timeout)
{
   struct virgl_screen *vscreen = virgl_screen(screen);
   struct virgl_winsys *vws = vscreen->vws;

   return vws->fence_wait(vws, fence, timeout);
}

static uint64_t
virgl_get_timestamp(struct pipe_screen *_screen)
{
   return os_time_get_nano();
}

static void
virgl_destroy_screen(struct pipe_screen *screen)
{
   struct virgl_screen *vscreen = virgl_screen(screen);
   struct virgl_winsys *vws = vscreen->vws;

600 601
   slab_destroy_parent(&vscreen->texture_transfer_pool);

602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
   if (vws)
      vws->destroy(vws);
   FREE(vscreen);
}

struct pipe_screen *
virgl_create_screen(struct virgl_winsys *vws)
{
   struct virgl_screen *screen = CALLOC_STRUCT(virgl_screen);

   if (!screen)
      return NULL;

   screen->vws = vws;
   screen->base.get_name = virgl_get_name;
   screen->base.get_vendor = virgl_get_vendor;
   screen->base.get_param = virgl_get_param;
   screen->base.get_shader_param = virgl_get_shader_param;
   screen->base.get_paramf = virgl_get_paramf;
   screen->base.is_format_supported = virgl_is_format_supported;
   screen->base.destroy = virgl_destroy_screen;
   screen->base.context_create = virgl_context_create;
   screen->base.flush_frontbuffer = virgl_flush_frontbuffer;
   screen->base.get_timestamp = virgl_get_timestamp;
   screen->base.fence_reference = virgl_fence_reference;
   //screen->base.fence_signalled = virgl_fence_signalled;
   screen->base.fence_finish = virgl_fence_finish;

   virgl_init_screen_resource_functions(&screen->base);

   vws->get_caps(vws, &screen->caps);

634
   screen->refcnt = 1;
635

636 637
   slab_create_parent(&screen->texture_transfer_pool, sizeof(struct virgl_transfer), 16);

638 639
   return &screen->base;
}