* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
-#include "virgl_vtest_winsys.h"
-#include "virgl_vtest_public.h"
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
-#include "state_tracker/drm_driver.h"
-#include "os/os_time.h"
+#include "util/os_time.h"
+#include "state_tracker/sw_winsys.h"
+
+#include "virgl_vtest_winsys.h"
+#include "virgl_vtest_public.h"
+
+static void *virgl_vtest_resource_map(struct virgl_winsys *vws,
+ struct virgl_hw_res *res);
+static void virgl_vtest_resource_unmap(struct virgl_winsys *vws,
+ struct virgl_hw_res *res);
-static void *virgl_vtest_resource_map(struct virgl_winsys *vws, struct virgl_hw_res *res);
-static void virgl_vtest_resource_unmap(struct virgl_winsys *vws, struct virgl_hw_res *res);
static inline boolean can_cache_resource(struct virgl_hw_res *res)
{
return res->cacheable == TRUE;
void *ptr;
uint32_t valid_stride;
- size = vtest_get_transfer_size(res, box, stride, layer_stride, level, &valid_stride);
+ size = vtest_get_transfer_size(res, box, stride, layer_stride, level,
+ &valid_stride);
+
+ /* The size calculated above is the full box size, but if this box origin
+ * is not zero we may have to correct the transfer size to not read past the
+ * end of the resource. The correct adjustment depends on various factors
+ * that are not documented, so instead of going though all the hops to get
+ * the size right up-front, we just make sure we don't read past the end.
+ * FIXME: figure out what it takes to actually get this right.
+ */
+ if (size + buf_offset > res->size)
+ size = res->size - buf_offset;
- virgl_vtest_send_transfer_cmd(vtws, VCMD_TRANSFER_PUT, res->res_handle,
+ virgl_vtest_send_transfer_put(vtws, res->res_handle,
level, stride, layer_stride,
- box, size);
+ box, size, buf_offset);
ptr = virgl_vtest_resource_map(vws, res);
virgl_vtest_send_transfer_put_data(vtws, ptr + buf_offset, size);
virgl_vtest_resource_unmap(vws, res);
void *ptr;
uint32_t valid_stride;
- size = vtest_get_transfer_size(res, box, stride, layer_stride, level, &valid_stride);
+ size = vtest_get_transfer_size(res, box, stride, layer_stride, level,
+ &valid_stride);
+ /* Don't ask for more pixels than available (see above) */
+ if (size + buf_offset > res->size)
+ size = res->size - buf_offset;
- virgl_vtest_send_transfer_cmd(vtws, VCMD_TRANSFER_GET, res->res_handle,
+ virgl_vtest_send_transfer_get(vtws, res->res_handle,
level, stride, layer_stride,
- box, size);
-
+ box, size, buf_offset);
ptr = virgl_vtest_resource_map(vws, res);
- virgl_vtest_recv_transfer_get_data(vtws, ptr + buf_offset, size, valid_stride, box, res->format);
+
+ /* This functions seems to be using a specific transfer resource that
+ * has exactly the box size and hence its src stride is equal to the target
+ * stride */
+ virgl_vtest_recv_transfer_get_data(vtws, ptr + buf_offset, size,
+ valid_stride, box, res->format, valid_stride);
+
virgl_vtest_resource_unmap(vws, res);
return 0;
}
struct list_head *curr, *next;
struct virgl_hw_res *res;
- pipe_mutex_lock(vtws->mutex);
+ mtx_lock(&vtws->mutex);
curr = vtws->delayed.next;
next = curr->next;
curr = next;
next = curr->next;
}
- pipe_mutex_unlock(vtws->mutex);
+ mtx_unlock(&vtws->mutex);
}
static void
if (!can_cache_resource(old)) {
virgl_hw_res_destroy(vtws, old);
} else {
- pipe_mutex_lock(vtws->mutex);
+ mtx_lock(&vtws->mutex);
virgl_cache_list_check_free(vtws);
old->start = os_time_get();
old->end = old->start + vtws->usecs;
LIST_ADDTAIL(&old->head, &vtws->delayed);
vtws->num_delayed++;
- pipe_mutex_unlock(vtws->mutex);
+ mtx_unlock(&vtws->mutex);
}
}
*dres = sres;
}
-static struct virgl_hw_res *virgl_vtest_winsys_resource_create(
- struct virgl_winsys *vws,
- enum pipe_texture_target target,
- uint32_t format,
- uint32_t bind,
- uint32_t width,
- uint32_t height,
- uint32_t depth,
- uint32_t array_size,
- uint32_t last_level,
- uint32_t nr_samples,
- uint32_t size)
+static struct virgl_hw_res *
+virgl_vtest_winsys_resource_create(struct virgl_winsys *vws,
+ enum pipe_texture_target target,
+ uint32_t format,
+ uint32_t bind,
+ uint32_t width,
+ uint32_t height,
+ uint32_t depth,
+ uint32_t array_size,
+ uint32_t last_level,
+ uint32_t nr_samples,
+ uint32_t size)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
struct virgl_hw_res *res;
return NULL;
if (bind & (VIRGL_BIND_DISPLAY_TARGET | VIRGL_BIND_SCANOUT)) {
- res->dt = vtws->sws->displaytarget_create(vtws->sws,
- bind,
- format,
- width,
- height,
- 64,
+ res->dt = vtws->sws->displaytarget_create(vtws->sws, bind, format,
+ width, height, 64, NULL,
&res->stride);
} else {
res->format = format;
res->height = height;
res->width = width;
- virgl_vtest_send_resource_create(vtws, handle, target, format, bind, width,
- height, depth, array_size, last_level,
- nr_samples);
+ res->size = size;
+ virgl_vtest_send_resource_create(vtws, handle, target, format, bind,
+ width, height, depth, array_size,
+ last_level, nr_samples, size);
res->res_handle = handle++;
pipe_reference_init(&res->reference, 1);
virgl_vtest_resource_reference(vtws, &hres, NULL);
}
-static void *virgl_vtest_resource_map(struct virgl_winsys *vws, struct virgl_hw_res *res)
+static void *virgl_vtest_resource_map(struct virgl_winsys *vws,
+ struct virgl_hw_res *res)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
}
}
-static void virgl_vtest_resource_unmap(struct virgl_winsys *vws, struct virgl_hw_res *res)
+static void virgl_vtest_resource_unmap(struct virgl_winsys *vws,
+ struct virgl_hw_res *res)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
if (res->mapped)
vtws->sws->displaytarget_unmap(vtws->sws, res->dt);
}
-static void virgl_vtest_resource_wait(struct virgl_winsys *vws, struct virgl_hw_res *res)
+static void virgl_vtest_resource_wait(struct virgl_winsys *vws,
+ struct virgl_hw_res *res)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
static inline int virgl_is_res_compat(struct virgl_vtest_winsys *vtws,
struct virgl_hw_res *res,
- uint32_t size, uint32_t bind, uint32_t format)
+ uint32_t size, uint32_t bind,
+ uint32_t format)
{
if (res->bind != bind)
return 0;
return 1;
}
-static struct virgl_hw_res *virgl_vtest_winsys_resource_cache_create(struct virgl_winsys *vws,
- enum pipe_texture_target target,
- uint32_t format,
- uint32_t bind,
- uint32_t width,
- uint32_t height,
- uint32_t depth,
- uint32_t array_size,
- uint32_t last_level,
- uint32_t nr_samples,
- uint32_t size)
+static struct virgl_hw_res *
+virgl_vtest_winsys_resource_cache_create(struct virgl_winsys *vws,
+ enum pipe_texture_target target,
+ uint32_t format,
+ uint32_t bind,
+ uint32_t width,
+ uint32_t height,
+ uint32_t depth,
+ uint32_t array_size,
+ uint32_t last_level,
+ uint32_t nr_samples,
+ uint32_t size)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
struct virgl_hw_res *res, *curr_res;
bind != VIRGL_BIND_VERTEX_BUFFER && bind != VIRGL_BIND_CUSTOM)
goto alloc;
- pipe_mutex_lock(vtws->mutex);
+ mtx_lock(&vtws->mutex);
res = NULL;
curr = vtws->delayed.next;
while (curr != &vtws->delayed) {
curr_res = LIST_ENTRY(struct virgl_hw_res, curr, head);
- if (!res && (ret = virgl_is_res_compat(vtws, curr_res, size, bind, format) > 0))
+ if (!res && ((ret = virgl_is_res_compat(vtws, curr_res, size, bind, format)) > 0))
res = curr_res;
else if (os_time_timeout(curr_res->start, curr_res->end, now)) {
LIST_DEL(&curr_res->head);
if (res) {
LIST_DEL(&res->head);
--vtws->num_delayed;
- pipe_mutex_unlock(vtws->mutex);
+ mtx_unlock(&vtws->mutex);
pipe_reference_init(&res->reference, 1);
return res;
}
- pipe_mutex_unlock(vtws->mutex);
+ mtx_unlock(&vtws->mutex);
alloc:
res = virgl_vtest_winsys_resource_create(vws, target, format, bind,
- width, height, depth, array_size,
- last_level, nr_samples, size);
+ width, height, depth, array_size,
+ last_level, nr_samples, size);
if (bind == VIRGL_BIND_CONSTANT_BUFFER || bind == VIRGL_BIND_INDEX_BUFFER ||
bind == VIRGL_BIND_VERTEX_BUFFER)
res->cacheable = TRUE;
return NULL;
cbuf->nres = 512;
- cbuf->res_bo = (struct virgl_hw_res **)
- CALLOC(cbuf->nres, sizeof(struct virgl_hw_buf*));
+ cbuf->res_bo = CALLOC(cbuf->nres, sizeof(struct virgl_hw_buf*));
if (!cbuf->res_bo) {
FREE(cbuf);
return NULL;
}
cbuf->ws = vws;
cbuf->base.buf = cbuf->buf;
+ cbuf->base.in_fence_fd = -1;
return &cbuf->base;
}
}
static boolean virgl_vtest_lookup_res(struct virgl_vtest_cmd_buf *cbuf,
- struct virgl_hw_res *res)
+ struct virgl_hw_res *res)
{
unsigned hash = res->res_handle & (sizeof(cbuf->is_handle_added)-1);
int i;
}
static void virgl_vtest_add_res(struct virgl_vtest_winsys *vtws,
- struct virgl_vtest_cmd_buf *cbuf, struct virgl_hw_res *res)
+ struct virgl_vtest_cmd_buf *cbuf,
+ struct virgl_hw_res *res)
{
unsigned hash = res->res_handle & (sizeof(cbuf->is_handle_added)-1);
- if (cbuf->cres > cbuf->nres) {
- fprintf(stderr,"failure to add relocation\n");
- return;
+ if (cbuf->cres >= cbuf->nres) {
+ unsigned new_nres = cbuf->nres + 256;
+ struct virgl_hw_res **new_re_bo = REALLOC(cbuf->res_bo,
+ cbuf->nres * sizeof(struct virgl_hw_buf*),
+ new_nres * sizeof(struct virgl_hw_buf*));
+ if (!new_re_bo) {
+ fprintf(stderr,"failure to add relocation %d, %d\n", cbuf->cres, cbuf->nres);
+ return;
+ }
+
+ cbuf->res_bo = new_re_bo;
+ cbuf->nres = new_nres;
}
cbuf->res_bo[cbuf->cres] = NULL;
cbuf->cres++;
}
-static int virgl_vtest_winsys_submit_cmd(struct virgl_winsys *vws, struct virgl_cmd_buf *_cbuf)
+static int virgl_vtest_winsys_submit_cmd(struct virgl_winsys *vws,
+ struct virgl_cmd_buf *_cbuf,
+ int in_fence_fd, int *out_fence_fd)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
struct virgl_vtest_cmd_buf *cbuf = virgl_vtest_cmd_buf(_cbuf);
if (cbuf->base.cdw == 0)
return 0;
+ assert(in_fence_fd == -1);
+ assert(out_fence_fd == NULL);
+
ret = virgl_vtest_submit_cmd(vtws, cbuf);
virgl_vtest_release_all_res(vtws, cbuf);
return ret;
}
-static void virgl_vtest_emit_res(struct virgl_winsys *vws, struct virgl_cmd_buf *_cbuf, struct virgl_hw_res *res, boolean write_buf)
+static void virgl_vtest_emit_res(struct virgl_winsys *vws,
+ struct virgl_cmd_buf *_cbuf,
+ struct virgl_hw_res *res, boolean write_buf)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
struct virgl_vtest_cmd_buf *cbuf = virgl_vtest_cmd_buf(_cbuf);
return TRUE;
}
-static int virgl_vtest_get_caps(struct virgl_winsys *vws, struct virgl_drm_caps *caps)
+static int virgl_vtest_get_caps(struct virgl_winsys *vws,
+ struct virgl_drm_caps *caps)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+
+ virgl_ws_fill_new_caps_defaults(caps);
return virgl_vtest_send_get_caps(vtws, caps);
}
static struct pipe_fence_handle *
-virgl_cs_create_fence(struct virgl_winsys *vws)
+virgl_cs_create_fence(struct virgl_winsys *vws, int fd)
{
struct virgl_hw_res *res;
res = virgl_vtest_winsys_resource_cache_create(vws,
PIPE_BUFFER,
PIPE_FORMAT_R8_UNORM,
- PIPE_BIND_CUSTOM,
+ VIRGL_BIND_CUSTOM,
8, 1, 1, 0, 0, 0, 8);
return (struct pipe_fence_handle *)res;
struct virgl_hw_res *res = virgl_hw_res(fence);
if (timeout == 0)
- return virgl_vtest_resource_is_busy(vdws, res);
+ return !virgl_vtest_resource_is_busy(vdws, res);
if (timeout != PIPE_TIMEOUT_INFINITE) {
int64_t start_time = os_time_get();
if (sub_box) {
box = *sub_box;
- offset = (res->stride * (box.y / util_format_get_blockheight(res->format))) + (box.x / util_format_get_blockwidth(res->format)) * util_format_get_blocksize(res->format);
+ offset = box.y / util_format_get_blockheight(res->format) * res->stride +
+ box.x / util_format_get_blockwidth(res->format) * util_format_get_blocksize(res->format);
} else {
box.z = layer;
box.width = res->width;
map = vtws->sws->displaytarget_map(vtws->sws, res->dt, 0);
/* execute a transfer */
- virgl_vtest_send_transfer_cmd(vtws, VCMD_TRANSFER_GET, res->res_handle,
- level, res->stride, 0, &box, size);
- virgl_vtest_recv_transfer_get_data(vtws, map + offset, size, valid_stride, &box, res->format);
+ virgl_vtest_send_transfer_get(vtws, res->res_handle,
+ level, res->stride, 0, &box, size, offset);
+
+ /* This functions gets the resource from the hardware backend that may have
+ * a hardware imposed stride that is different from the IOV stride used to
+ * get the data. */
+ virgl_vtest_recv_transfer_get_data(vtws, map + offset, size, valid_stride,
+ &box, res->format,
+ util_format_get_stride(res->format, res->width));
+
vtws->sws->displaytarget_unmap(vtws->sws, res->dt);
- vtws->sws->displaytarget_display(vtws->sws, res->dt, winsys_drawable_handle, sub_box);
+ vtws->sws->displaytarget_display(vtws->sws, res->dt, winsys_drawable_handle,
+ sub_box);
}
static void
virgl_cache_flush(vtws);
- pipe_mutex_destroy(vtws->mutex);
+ mtx_destroy(&vtws->mutex);
FREE(vtws);
}
vtws->usecs = 1000000;
LIST_INITHEAD(&vtws->delayed);
- pipe_mutex_init(vtws->mutex);
+ (void) mtx_init(&vtws->mutex, mtx_plain);
vtws->base.destroy = virgl_vtest_winsys_destroy;
vtws->base.cs_create_fence = virgl_cs_create_fence;
vtws->base.fence_wait = virgl_fence_wait;
vtws->base.fence_reference = virgl_fence_reference;
+ vtws->base.supports_fences = 0;
vtws->base.flush_frontbuffer = virgl_vtest_flush_frontbuffer;