vtest_renderer.c 9.62 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
/**************************************************************************
 *
 * Copyright (C) 2015 Red Hat Inc.
 *
 * 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
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * 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 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 NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS 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.
 *
 **************************************************************************/
24
#include <stdlib.h>
25
#include <stdio.h>
Dave Airlie's avatar
Dave Airlie committed
26
#include <string.h>
27
#include <unistd.h>
28 29
#include <fcntl.h>

30 31
#include "virglrenderer.h"

32 33
#include <sys/uio.h>
#include "vtest.h"
Dave Airlie's avatar
Dave Airlie committed
34
#include "vtest_protocol.h"
35
#include "util.h"
Dave Airlie's avatar
Dave Airlie committed
36 37

static int ctx_id = 1;
38 39 40 41 42 43 44 45
static int fence_id = 1;

static int last_fence;
static void vtest_write_fence(void *cookie, uint32_t fence_id)
{
  last_fence = fence_id;
}

46 47
struct virgl_renderer_callbacks vtest_cbs = {
    .version = 1,
48
    .write_fence = vtest_write_fence,
49 50 51
};

struct vtest_renderer {
52 53
  int in_fd;
  int out_fd;
54 55 56 57
};

struct vtest_renderer renderer;

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
struct virgl_box {
	uint32_t x, y, z;
	uint32_t w, h, d;
};

static int vtest_block_write(int fd, void *buf, int size)
{
   void *ptr = buf;
   int left;
   int ret;
   left = size;
   do {
      ret = write(fd, ptr, left);
      if (ret < 0)
         return -errno;
      left -= ret;
      ptr += ret;
   } while (left);
   return size;
}

int vtest_block_read(int fd, void *buf, int size)
{
   void *ptr = buf;
   int left;
   int ret;
84 85
   static int savefd = -1;

86 87 88
   left = size;
   do {
      ret = read(fd, ptr, left);
89 90
      if (ret <= 0)
	return ret == -1 ? -errno : 0;
91 92 93
      left -= ret;
      ptr += ret;
   } while (left);
94 95 96 97 98 99 100 101 102 103 104 105 106 107
   if (getenv("VTEST_SAVE")) {
      if (savefd == -1) {
         savefd = open(getenv("VTEST_SAVE"),
                       O_CLOEXEC|O_CREAT|O_WRONLY|O_TRUNC|O_DSYNC, S_IRUSR|S_IWUSR);
         if (savefd == -1) {
            perror("error opening save file");
            exit(1);
         }
      }
      if (write(savefd, buf, size) != size) {
         perror("failed to save");
         exit(1);
      }
   }
108 109 110
   return size;
}

111
int vtest_create_renderer(int in_fd, int out_fd, uint32_t length)
112
{
113
    char *vtestname;
Dave Airlie's avatar
Dave Airlie committed
114 115
    int ret;

116 117
    renderer.in_fd = in_fd;
    renderer.out_fd = out_fd;
118

119 120 121 122 123 124 125
    ret = virgl_renderer_init(&renderer,
                              VIRGL_RENDERER_USE_EGL |
                              VIRGL_RENDERER_THREAD_SYNC, &vtest_cbs);
    if (ret) {
      fprintf(stderr, "failed to initialise renderer.\n");
      return -1;
    }
Dave Airlie's avatar
Dave Airlie committed
126

127 128 129 130
    vtestname = malloc(length);
    if (!vtestname)
      return -1;

131
    ret = vtest_block_read(renderer.in_fd, vtestname, length);
132 133 134 135 136
    if (ret != length) {
       ret = -1;
       goto end;
    }

Dave Airlie's avatar
Dave Airlie committed
137
    ret = virgl_renderer_context_create(ctx_id, strlen(vtestname), vtestname);
138 139 140

end:
    free(vtestname);
Dave Airlie's avatar
Dave Airlie committed
141
    return ret;
142 143
}

144 145 146 147
void vtest_destroy_renderer(void)
{
  virgl_renderer_context_destroy(ctx_id);
  virgl_renderer_cleanup(&renderer);
148 149
  renderer.in_fd = -1;
  renderer.out_fd = -1;
150 151
}

152 153 154 155 156
int vtest_send_caps(void)
{
    uint32_t  max_ver, max_size;
    void *caps_buf;
    uint32_t hdr_buf[2];
157 158
    int ret;

159 160 161 162 163 164 165 166 167 168
    virgl_renderer_get_cap_set(1, &max_ver, &max_size);

    caps_buf = malloc(max_size);
    if (!caps_buf)
	return -1;
    
    virgl_renderer_fill_caps(1, 1, caps_buf);

    hdr_buf[0] = max_size + 1;
    hdr_buf[1] = 1;
169
    ret = vtest_block_write(renderer.out_fd, hdr_buf, 8);
170
    if (ret < 0)
171
       goto end;
172
    vtest_block_write(renderer.out_fd, caps_buf, max_size);
173
    if (ret < 0)
174
       goto end;
175

176 177
end:
    free(caps_buf);
178 179
    return 0;
}
Dave Airlie's avatar
Dave Airlie committed
180 181 182 183 184 185 186

int vtest_create_resource(void)
{
    uint32_t res_create_buf[VCMD_RES_CREATE_SIZE];
    struct virgl_renderer_resource_create_args args;
    int ret;

187
    ret = vtest_block_read(renderer.in_fd, &res_create_buf, sizeof(res_create_buf));
Dave Airlie's avatar
Dave Airlie committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
    if (ret != sizeof(res_create_buf))
	return -1;
	
    args.handle = res_create_buf[VCMD_RES_CREATE_RES_HANDLE];
    args.target = res_create_buf[VCMD_RES_CREATE_TARGET];
    args.format = res_create_buf[VCMD_RES_CREATE_FORMAT];
    args.bind = res_create_buf[VCMD_RES_CREATE_BIND];

    args.width = res_create_buf[VCMD_RES_CREATE_WIDTH];
    args.height = res_create_buf[VCMD_RES_CREATE_HEIGHT];
    args.depth = res_create_buf[VCMD_RES_CREATE_DEPTH];
    args.array_size = res_create_buf[VCMD_RES_CREATE_ARRAY_SIZE];
    args.last_level = res_create_buf[VCMD_RES_CREATE_LAST_LEVEL];
    args.nr_samples = res_create_buf[VCMD_RES_CREATE_NR_SAMPLES];
    args.flags = 0;

    ret = virgl_renderer_resource_create(&args, NULL, 0);

    virgl_renderer_ctx_attach_resource(ctx_id, args.handle);
    return ret;
}

int vtest_resource_unref(void)
{
    uint32_t res_unref_buf[VCMD_RES_UNREF_SIZE];
    int ret;
    uint32_t handle;

216
    ret = vtest_block_read(renderer.in_fd, &res_unref_buf, sizeof(res_unref_buf));
Dave Airlie's avatar
Dave Airlie committed
217 218 219 220 221 222 223 224
    if (ret != sizeof(res_unref_buf))
      return -1;

    handle = res_unref_buf[VCMD_RES_UNREF_RES_HANDLE];
    virgl_renderer_ctx_attach_resource(ctx_id, handle);
    virgl_renderer_resource_unref(handle);
    return 0;
}
Dave Airlie's avatar
Dave Airlie committed
225 226 227 228 229 230 231 232 233 234

int vtest_submit_cmd(uint32_t length_dw)
{
    uint32_t *cbuf;
    int ret;

    cbuf = malloc(length_dw * 4);
    if (!cbuf)
	return -1;

235
    ret = vtest_block_read(renderer.in_fd, cbuf, length_dw * 4);
Dave Airlie's avatar
Dave Airlie committed
236 237 238 239 240 241 242 243
    if (ret != length_dw * 4)
	return -1;

    virgl_renderer_submit_cmd(cbuf, ctx_id, length_dw);

    free(cbuf);
    return 0;
}
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

#define DECODE_TRANSFER \
  do {							\
  handle = thdr_buf[VCMD_TRANSFER_RES_HANDLE];		\
  level = thdr_buf[VCMD_TRANSFER_LEVEL];		\
  stride = thdr_buf[VCMD_TRANSFER_STRIDE];		\
  layer_stride = thdr_buf[VCMD_TRANSFER_LAYER_STRIDE];	\
  box.x = thdr_buf[VCMD_TRANSFER_X];			\
  box.y = thdr_buf[VCMD_TRANSFER_Y];			\
  box.z = thdr_buf[VCMD_TRANSFER_Z];			\
  box.w = thdr_buf[VCMD_TRANSFER_WIDTH];		\
  box.h = thdr_buf[VCMD_TRANSFER_HEIGHT];		\
  box.d = thdr_buf[VCMD_TRANSFER_DEPTH];		\
  data_size = thdr_buf[VCMD_TRANSFER_DATA_SIZE];		\
  } while(0)


int vtest_transfer_get(uint32_t length_dw)
{
    uint32_t thdr_buf[VCMD_TRANSFER_HDR_SIZE];
    int ret;
    int level;
    uint32_t stride, layer_stride, handle;
    struct virgl_box box;
    uint32_t data_size;
    void *ptr;
    struct iovec iovec;

272
    ret = vtest_block_read(renderer.in_fd, thdr_buf, VCMD_TRANSFER_HDR_SIZE * 4);
273 274 275 276 277 278 279 280 281 282 283
    if (ret != VCMD_TRANSFER_HDR_SIZE * 4)
      return ret;

    DECODE_TRANSFER;

    ptr = malloc(data_size);
    if (!ptr)
      return -ENOMEM;

    iovec.iov_len = data_size;
    iovec.iov_base = ptr;
284
    ret = virgl_renderer_transfer_read_iov(handle,
285 286 287 288 289 290 291
				     ctx_id,
				     level,
				     stride,
				     layer_stride,
				     &box,
				     0,
				     &iovec, 1);
292 293
    if (ret)
      fprintf(stderr," transfer read failed %d\n", ret);
294
    ret = vtest_block_write(renderer.out_fd, ptr, data_size);
295 296
    if (ret < 0)
      return ret;
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

    free(ptr);
    return 0;
}

int vtest_transfer_put(uint32_t length_dw)
{
    uint32_t thdr_buf[VCMD_TRANSFER_HDR_SIZE];
    int ret;
    int level;
    uint32_t stride, layer_stride, handle;
    struct virgl_box box;
    uint32_t data_size;
    void *ptr;
    struct iovec iovec;
312

313
    ret = vtest_block_read(renderer.in_fd, thdr_buf, VCMD_TRANSFER_HDR_SIZE * 4);
314 315 316 317 318 319 320 321 322
    if (ret != VCMD_TRANSFER_HDR_SIZE * 4)
      return ret;

    DECODE_TRANSFER;

    ptr = malloc(data_size);
    if (!ptr)
      return -ENOMEM;

323
    ret = vtest_block_read(renderer.in_fd, ptr, data_size);
324 325
    if (ret < 0)
      return ret;
326 327 328

    iovec.iov_len = data_size;
    iovec.iov_base = ptr;
329 330 331 332 333 334 335 336 337 338
    ret = virgl_renderer_transfer_write_iov(handle,
					    ctx_id,
					    level,
					    stride,
					    layer_stride,
					    &box,
					    0,
					    &iovec, 1);
    if (ret)
      fprintf(stderr," transfer write failed %d\n", ret);
339 340 341 342 343 344 345
    free(ptr);
    return 0;
}

int vtest_resource_busy_wait(void)
{
  uint32_t bw_buf[VCMD_BUSY_WAIT_SIZE];
346
  int ret, fd;
347 348 349 350
  int flags;
  uint32_t hdr_buf[VTEST_HDR_SIZE];
  uint32_t reply_buf[1];
  bool busy = false;
351
  ret = vtest_block_read(renderer.in_fd, &bw_buf, sizeof(bw_buf));
352 353 354
  if (ret != sizeof(bw_buf))
    return -1;

Dave Airlie's avatar
Dave Airlie committed
355
  /*  handle = bw_buf[VCMD_BUSY_WAIT_HANDLE]; unused as of now */
356 357 358 359
  flags = bw_buf[VCMD_BUSY_WAIT_FLAGS];

  if (flags == VCMD_BUSY_WAIT_FLAG_WAIT) {
    do {
360 361 362 363 364 365 366
       if (last_fence == (fence_id - 1))
          break;

       fd = virgl_renderer_get_poll_fd();
       if (fd != -1)
          vtest_wait_for_fd_read(fd);
       virgl_renderer_poll();
367 368 369 370 371 372 373 374 375 376
    } while (1);
    busy = false;
  } else {
    busy = last_fence != (fence_id - 1);
  }

  hdr_buf[VTEST_CMD_LEN] = 1;
  hdr_buf[VTEST_CMD_ID] = VCMD_RESOURCE_BUSY_WAIT;
  reply_buf[0] = busy ? 1 : 0;

377
  ret = vtest_block_write(renderer.out_fd, hdr_buf, sizeof(hdr_buf));
378 379 380
  if (ret < 0)
    return ret;

381
  ret = vtest_block_write(renderer.out_fd, reply_buf, sizeof(reply_buf));
382 383 384
  if (ret < 0)
    return ret;

385 386 387 388 389 390 391 392 393 394 395 396
  return 0;
}

int vtest_renderer_create_fence(void)
{
  virgl_renderer_create_fence(fence_id++, ctx_id);
  return 0;
}

int vtest_poll(void)
{
  virgl_renderer_poll();
397
  return 0;
398
}