Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2014 Advanced Micro Devices, Inc.
4
 * All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice (including the
15
 * next paragraph) shall be included in all copies or substantial portions
16
 * of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 **************************************************************************/
27
 
28
#include "util/u_tests.h"
29
 
30
#include "util/u_draw_quad.h"
31
#include "util/u_format.h"
32
#include "util/u_inlines.h"
33
#include "util/u_memory.h"
34
#include "util/u_simple_shaders.h"
35
#include "util/u_surface.h"
36
#include "util/u_string.h"
37
#include "util/u_tile.h"
38
#include "tgsi/tgsi_strings.h"
39
#include "tgsi/tgsi_text.h"
40
#include "cso_cache/cso_context.h"
41
#include 
42
 
43
#define TOLERANCE 0.01
44
 
45
static struct pipe_resource *
46
util_create_texture2d(struct pipe_screen *screen, unsigned width,
47
                      unsigned height, enum pipe_format format)
48
{
49
   struct pipe_resource templ = {{0}};
50
 
51
   templ.target = PIPE_TEXTURE_2D;
52
   templ.width0 = width;
53
   templ.height0 = height;
54
   templ.depth0 = 1;
55
   templ.array_size = 1;
56
   templ.format = format;
57
   templ.usage = PIPE_USAGE_DEFAULT;
58
   templ.bind = PIPE_BIND_SAMPLER_VIEW |
59
                (util_format_is_depth_or_stencil(format) ?
60
                    PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET);
61
 
62
   return screen->resource_create(screen, &templ);
63
}
64
 
65
static void
66
util_set_framebuffer_cb0(struct cso_context *cso, struct pipe_context *ctx,
67
			 struct pipe_resource *tex)
68
{
69
   struct pipe_surface templ = {{0}}, *surf;
70
   struct pipe_framebuffer_state fb = {0};
71
 
72
   templ.format = tex->format;
73
   surf = ctx->create_surface(ctx, tex, &templ);
74
 
75
   fb.width = tex->width0;
76
   fb.height = tex->height0;
77
   fb.cbufs[0] = surf;
78
   fb.nr_cbufs = 1;
79
 
80
   cso_set_framebuffer(cso, &fb);
81
   pipe_surface_reference(&surf, NULL);
82
}
83
 
84
static void
85
util_set_blend_normal(struct cso_context *cso)
86
{
87
   struct pipe_blend_state blend = {0};
88
 
89
   blend.rt[0].colormask = PIPE_MASK_RGBA;
90
   cso_set_blend(cso, &blend);
91
}
92
 
93
static void
94
util_set_dsa_disable(struct cso_context *cso)
95
{
96
   struct pipe_depth_stencil_alpha_state dsa = {{0}};
97
 
98
   cso_set_depth_stencil_alpha(cso, &dsa);
99
}
100
 
101
static void
102
util_set_rasterizer_normal(struct cso_context *cso)
103
{
104
   struct pipe_rasterizer_state rs = {0};
105
 
106
   rs.half_pixel_center = 1;
107
   rs.bottom_edge_rule = 1;
108
   rs.depth_clip = 1;
109
 
110
   cso_set_rasterizer(cso, &rs);
111
}
112
 
113
static void
114
util_set_max_viewport(struct cso_context *cso, struct pipe_resource *tex)
115
{
116
   struct pipe_viewport_state viewport;
117
 
118
   viewport.scale[0] = 0.5f * tex->width0;
119
   viewport.scale[1] = 0.5f * tex->height0;
120
   viewport.scale[2] = 1.0f;
121
   viewport.translate[0] = 0.5f * tex->width0;
122
   viewport.translate[1] = 0.5f * tex->height0;
123
   viewport.translate[2] = 0.0f;
124
 
125
   cso_set_viewport(cso, &viewport);
126
}
127
 
128
static void
129
util_set_interleaved_vertex_elements(struct cso_context *cso,
130
                                     unsigned num_elements)
131
{
132
   int i;
133
   struct pipe_vertex_element *velem =
134
      calloc(1, num_elements * sizeof(struct pipe_vertex_element));
135
 
136
   for (i = 0; i < num_elements; i++) {
137
      velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
138
      velem[i].src_offset = i * 16;
139
   }
140
 
141
   cso_set_vertex_elements(cso, num_elements, velem);
142
   free(velem);
143
}
144
 
145
static void *
146
util_set_passthrough_vertex_shader(struct cso_context *cso,
147
                                   struct pipe_context *ctx,
148
                                   bool window_space)
149
{
150
   static const uint vs_attribs[] = {
151
      TGSI_SEMANTIC_POSITION,
152
      TGSI_SEMANTIC_GENERIC
153
   };
154
   static const uint vs_indices[] = {0, 0};
155
   void *vs;
156
 
157
   vs = util_make_vertex_passthrough_shader(ctx, 2, vs_attribs, vs_indices,
158
                                            window_space);
159
   cso_set_vertex_shader_handle(cso, vs);
160
   return vs;
161
}
162
 
163
static void
164
util_set_common_states_and_clear(struct cso_context *cso, struct pipe_context *ctx,
165
                                 struct pipe_resource *cb)
166
{
167
   static const float clear_color[] = {0.1, 0.1, 0.1, 0.1};
168
 
169
   util_set_framebuffer_cb0(cso, ctx, cb);
170
   util_set_blend_normal(cso);
171
   util_set_dsa_disable(cso);
172
   util_set_rasterizer_normal(cso);
173
   util_set_max_viewport(cso, cb);
174
 
175
   ctx->clear(ctx, PIPE_CLEAR_COLOR0, (void*)clear_color, 0, 0);
176
}
177
 
178
static void
179
util_draw_fullscreen_quad(struct cso_context *cso)
180
{
181
   static float vertices[] = {
182
     -1, -1, 0, 1,   0, 0, 0, 0,
183
     -1,  1, 0, 1,   0, 1, 0, 0,
184
      1,  1, 0, 1,   1, 1, 0, 0,
185
      1, -1, 0, 1,   1, 0, 0, 0
186
   };
187
   util_set_interleaved_vertex_elements(cso, 2);
188
   util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
189
}
190
 
191
/**
192
 * Probe and test if the rectangle contains the expected color.
193
 *
194
 * If "num_expected_colors" > 1, at least one expected color must match
195
 * the probed color. "expected" should be an array of 4*num_expected_colors
196
 * floats.
197
 */
198
static bool
199
util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex,
200
                           unsigned offx, unsigned offy, unsigned w,
201
                           unsigned h,
202
                           const float *expected,
203
                           unsigned num_expected_colors)
204
{
205
   struct pipe_transfer *transfer;
206
   void *map;
207
   float *pixels = malloc(w * h * 4 * sizeof(float));
208
   int x,y,e,c;
209
   bool pass = true;
210
 
211
   map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ,
212
                           offx, offy, w, h, &transfer);
213
   pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels);
214
   pipe_transfer_unmap(ctx, transfer);
215
 
216
   for (e = 0; e < num_expected_colors; e++) {
217
      for (y = 0; y < h; y++) {
218
         for (x = 0; x < w; x++) {
219
            float *probe = &pixels[(y*w + x)*4];
220
 
221
            for (c = 0; c < 4; c++) {
222
               if (fabs(probe[c] - expected[e*4+c]) >= TOLERANCE) {
223
                  if (e < num_expected_colors-1)
224
                     goto next_color; /* test the next expected color */
225
 
226
                  printf("Probe color at (%i,%i),  ", offx+x, offy+y);
227
                  printf("Expected: %.3f, %.3f, %.3f, %.3f,  ",
228
                         expected[e*4], expected[e*4+1],
229
                         expected[e*4+2], expected[e*4+3]);
230
                  printf("Got: %.3f, %.3f, %.3f, %.3f\n",
231
                         probe[0], probe[1], probe[2], probe[2]);
232
                  pass = false;
233
                  goto done;
234
               }
235
            }
236
         }
237
      }
238
      break; /* this color was successful */
239
 
240
   next_color:;
241
   }
242
done:
243
 
244
   free(pixels);
245
   return pass;
246
}
247
 
248
static bool
249
util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex,
250
                     unsigned offx, unsigned offy, unsigned w, unsigned h,
251
                     const float *expected)
252
{
253
   return util_probe_rect_rgba_multi(ctx, tex, offx, offy, w, h, expected, 1);
254
}
255
 
256
enum {
257
   SKIP = -1,
258
   FAIL = 0, /* also "false" */
259
   PASS = 1 /* also "true" */
260
};
261
 
262
static void
263
util_report_result_helper(int status, const char *name, ...)
264
{
265
   char buf[256];
266
   va_list ap;
267
 
268
   va_start(ap, name);
269
   util_vsnprintf(buf, sizeof(buf), name, ap);
270
   va_end(ap);
271
 
272
   printf("Test(%s) = %s\n", buf,
273
          status == SKIP ? "skip" :
274
          status == PASS ? "pass" : "fail");
275
}
276
 
277
#define util_report_result(status) util_report_result_helper(status, __func__)
278
 
279
/**
280
 * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION.
281
 *
282
 * The viewport state is set as usual, but it should have no effect.
283
 * Clipping should also be disabled.
284
 *
285
 * POSITION.xyz should already be multiplied by 1/w and POSITION.w should
286
 * contain 1/w. By setting w=0, we can test that POSITION.xyz isn't
287
 * multiplied by 1/w (otherwise nothing would be rendered).
288
 *
289
 * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w
290
 *       during perspective interpolation is not tested.
291
 */
292
static void
293
tgsi_vs_window_space_position(struct pipe_context *ctx)
294
{
295
   struct cso_context *cso;
296
   struct pipe_resource *cb;
297
   void *fs, *vs;
298
   bool pass = true;
299
   static const float red[] = {1, 0, 0, 1};
300
 
301
   if (!ctx->screen->get_param(ctx->screen,
302
                               PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) {
303
      util_report_result(SKIP);
304
      return;
305
   }
306
 
307
   cso = cso_create_context(ctx);
308
   cb = util_create_texture2d(ctx->screen, 256, 256,
309
                              PIPE_FORMAT_R8G8B8A8_UNORM);
310
   util_set_common_states_and_clear(cso, ctx, cb);
311
 
312
   /* Fragment shader. */
313
   fs = util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC,
314
                                       TGSI_INTERPOLATE_LINEAR, TRUE);
315
   cso_set_fragment_shader_handle(cso, fs);
316
 
317
   /* Vertex shader. */
318
   vs = util_set_passthrough_vertex_shader(cso, ctx, true);
319
 
320
   /* Draw. */
321
   {
322
      static float vertices[] = {
323
          0,   0, 0, 0,   1,  0, 0, 1,
324
          0, 256, 0, 0,   1,  0, 0, 1,
325
        256, 256, 0, 0,   1,  0, 0, 1,
326
        256,   0, 0, 0,   1,  0, 0, 1,
327
      };
328
      util_set_interleaved_vertex_elements(cso, 2);
329
      util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
330
   }
331
 
332
   /* Probe pixels. */
333
   pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0,
334
                                       cb->width0, cb->height0, red);
335
 
336
   /* Cleanup. */
337
   cso_destroy_context(cso);
338
   ctx->delete_vs_state(ctx, vs);
339
   ctx->delete_fs_state(ctx, fs);
340
   pipe_resource_reference(&cb, NULL);
341
 
342
   util_report_result(pass);
343
}
344
 
345
static void
346
null_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target)
347
{
348
   struct cso_context *cso;
349
   struct pipe_resource *cb;
350
   void *fs, *vs;
351
   bool pass = true;
352
   /* 2 expected colors: */
353
   static const float expected_tex[] = {0, 0, 0, 1,
354
                                        0, 0, 0, 0};
355
   static const float expected_buf[] = {0, 0, 0, 0};
356
   const float *expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ?
357
                              expected_buf : expected_tex;
358
   unsigned num_expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ? 1 : 2;
359
 
360
   if (tgsi_tex_target == TGSI_TEXTURE_BUFFER &&
361
       !ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) {
362
      util_report_result_helper(SKIP, "%s: %s", __func__,
363
                                tgsi_texture_names[tgsi_tex_target]);
364
      return;
365
   }
366
 
367
   cso = cso_create_context(ctx);
368
   cb = util_create_texture2d(ctx->screen, 256, 256,
369
                              PIPE_FORMAT_R8G8B8A8_UNORM);
370
   util_set_common_states_and_clear(cso, ctx, cb);
371
 
372
   ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
373
 
374
   /* Fragment shader. */
375
   fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target,
376
                                      TGSI_INTERPOLATE_LINEAR);
377
   cso_set_fragment_shader_handle(cso, fs);
378
 
379
   /* Vertex shader. */
380
   vs = util_set_passthrough_vertex_shader(cso, ctx, false);
381
   util_draw_fullscreen_quad(cso);
382
 
383
   /* Probe pixels. */
384
   pass = pass && util_probe_rect_rgba_multi(ctx, cb, 0, 0,
385
                                  cb->width0, cb->height0, expected,
386
                                  num_expected);
387
 
388
   /* Cleanup. */
389
   cso_destroy_context(cso);
390
   ctx->delete_vs_state(ctx, vs);
391
   ctx->delete_fs_state(ctx, fs);
392
   pipe_resource_reference(&cb, NULL);
393
 
394
   util_report_result_helper(pass, "%s: %s", __func__,
395
                             tgsi_texture_names[tgsi_tex_target]);
396
}
397
 
398
static void
399
null_constant_buffer(struct pipe_context *ctx)
400
{
401
   struct cso_context *cso;
402
   struct pipe_resource *cb;
403
   void *fs, *vs;
404
   bool pass = true;
405
   static const float zero[] = {0, 0, 0, 0};
406
 
407
   cso = cso_create_context(ctx);
408
   cb = util_create_texture2d(ctx->screen, 256, 256,
409
                              PIPE_FORMAT_R8G8B8A8_UNORM);
410
   util_set_common_states_and_clear(cso, ctx, cb);
411
 
412
   ctx->set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT, 0, NULL);
413
 
414
   /* Fragment shader. */
415
   {
416
      static const char *text = /* I don't like ureg... */
417
            "FRAG\n"
418
            "DCL CONST[0]\n"
419
            "DCL OUT[0], COLOR\n"
420
 
421
            "MOV OUT[0], CONST[0]\n"
422
            "END\n";
423
      struct tgsi_token tokens[1000];
424
      struct pipe_shader_state state = {tokens};
425
 
426
      if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
427
         puts("Can't compile a fragment shader.");
428
         util_report_result(FAIL);
429
         return;
430
      }
431
      fs = ctx->create_fs_state(ctx, &state);
432
      cso_set_fragment_shader_handle(cso, fs);
433
   }
434
 
435
   /* Vertex shader. */
436
   vs = util_set_passthrough_vertex_shader(cso, ctx, false);
437
   util_draw_fullscreen_quad(cso);
438
 
439
   /* Probe pixels. */
440
   pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0, cb->width0,
441
                                       cb->height0, zero);
442
 
443
   /* Cleanup. */
444
   cso_destroy_context(cso);
445
   ctx->delete_vs_state(ctx, vs);
446
   ctx->delete_fs_state(ctx, fs);
447
   pipe_resource_reference(&cb, NULL);
448
 
449
   util_report_result(pass);
450
}
451
 
452
/**
453
 * Run all tests. This should be run with a clean context after
454
 * context_create.
455
 */
456
void
457
util_run_tests(struct pipe_screen *screen)
458
{
459
   struct pipe_context *ctx = screen->context_create(screen, NULL);
460
 
461
   tgsi_vs_window_space_position(ctx);
462
   null_sampler_view(ctx, TGSI_TEXTURE_2D);
463
   null_sampler_view(ctx, TGSI_TEXTURE_BUFFER);
464
   null_constant_buffer(ctx);
465
 
466
   ctx->destroy(ctx);
467
 
468
   puts("Done. Exiting..");
469
   exit(0);
470
}