static struct svga_winsys_surface * vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws, SVGA3dSurfaceFlags flags, SVGA3dSurfaceFormat format, SVGA3dSize size, uint32 numFaces, uint32 numMipLevels) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); struct vmw_svga_winsys_surface *surface; surface = CALLOC_STRUCT(vmw_svga_winsys_surface); if(!surface) goto no_surface; pipe_reference_init(&surface->refcnt, 1); p_atomic_set(&surface->validated, 0); surface->screen = vws; surface->sid = vmw_ioctl_surface_create(vws, flags, format, size, numFaces, numMipLevels); if(surface->sid == SVGA3D_INVALID_ID) goto no_sid; return svga_winsys_surface(surface); no_sid: FREE(surface); no_surface: return NULL; }
static void vmw_svga_winsys_destroy(struct svga_winsys_screen *sws) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); vmw_winsys_destroy(vws); }
static int vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws, struct pipe_fence_handle *fence, unsigned flag) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); return vmw_fence_finish(vws, fence, flag); }
static int vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws, struct pipe_fence_handle *fence, unsigned flag) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); (void)flag; return vmw_ioctl_fence_finish(vws, vmw_fence(fence)); }
static void vmw_svga_winsys_fence_reference(struct svga_winsys_screen *sws, struct pipe_fence_handle **pdst, struct pipe_fence_handle *src) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); vmw_fence_reference(vws, pdst, src); }
static void vmw_dri1_present_locked(struct pipe_context *locked_pipe, struct pipe_surface *surf, const struct drm_clip_rect *rect, unsigned int num_clip, int x_draw, int y_draw, const struct drm_clip_rect *bbox, struct pipe_fence_handle **p_fence) { struct svga_winsys_surface *srf = svga_screen_texture_get_winsys_surface(surf->texture); struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); struct vmw_winsys_screen *vws = vmw_winsys_screen(svga_winsys_screen(locked_pipe->screen)); struct drm_clip_rect clip; int i; struct { SVGA3dCmdHeader header; SVGA3dCmdPresent body; SVGA3dCopyRect rect; } cmd; boolean visible = FALSE; uint32_t fence_seq = 0; VMW_FUNC; cmd.header.id = SVGA_3D_CMD_PRESENT; cmd.header.size = sizeof cmd.body + sizeof cmd.rect; cmd.body.sid = vsrf->sid; for (i = 0; i < num_clip; ++i) { if (!vmw_dri1_intersect_src_bbox(&clip, x_draw, y_draw, rect++, bbox)) continue; cmd.rect.x = clip.x1; cmd.rect.y = clip.y1; cmd.rect.w = clip.x2 - clip.x1; cmd.rect.h = clip.y2 - clip.y1; cmd.rect.srcx = (int)clip.x1 - x_draw; cmd.rect.srcy = (int)clip.y1 - y_draw; vmw_printf("%s: Clip %d x %d y %d w %d h %d srcx %d srcy %d\n", __FUNCTION__, i, cmd.rect.x, cmd.rect.y, cmd.rect.w, cmd.rect.h, cmd.rect.srcx, cmd.rect.srcy); vmw_ioctl_command(vws, &cmd, sizeof cmd.header + cmd.header.size, &fence_seq); visible = TRUE; } *p_fence = (visible) ? vmw_pipe_fence(fence_seq) : NULL; vmw_svga_winsys_surface_reference(&vsrf, NULL); }
static SVGA3dHardwareVersion vmw_svga_winsys_get_hw_version(struct svga_winsys_screen *sws) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); if (sws->have_gb_objects) return SVGA3D_HWVERSION_WS8_B1; return (SVGA3dHardwareVersion) vws->ioctl.hwversion; }
static SVGA3dHardwareVersion vmw_svga_winsys_get_hw_version(struct svga_winsys_screen *sws) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); if (!vws->ioctl.fifo_map) { return 0; } return vws->ioctl.fifo_map[SVGA_FIFO_3D_HWVERSION]; }
struct svga_winsys_context * vmw_svga_winsys_context_create(struct svga_winsys_screen *sws) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); struct vmw_svga_winsys_context *vswc; vswc = CALLOC_STRUCT(vmw_svga_winsys_context); if(!vswc) return NULL; vswc->base.destroy = vmw_swc_destroy; vswc->base.reserve = vmw_swc_reserve; vswc->base.surface_relocation = vmw_swc_surface_relocation; vswc->base.region_relocation = vmw_swc_region_relocation; vswc->base.mob_relocation = vmw_swc_mob_relocation; vswc->base.context_relocation = vmw_swc_context_relocation; vswc->base.shader_relocation = vmw_swc_shader_relocation; vswc->base.commit = vmw_swc_commit; vswc->base.flush = vmw_swc_flush; vswc->base.surface_map = vmw_svga_winsys_surface_map; vswc->base.surface_unmap = vmw_svga_winsys_surface_unmap; vswc->base.cid = vmw_ioctl_context_create(vws); vswc->base.have_gb_objects = sws->have_gb_objects; vswc->vws = vws; vswc->command.size = VMW_COMMAND_SIZE; vswc->surface.size = VMW_SURFACE_RELOCS; vswc->shader.size = VMW_SHADER_RELOCS; vswc->region.size = VMW_REGION_RELOCS; vswc->validate = pb_validate_create(); if(!vswc->validate) goto out_no_validate; vswc->hash = util_hash_table_create(vmw_hash_ptr, vmw_ptr_compare); if (!vswc->hash) goto out_no_hash; #ifdef DEBUG vswc->fctx = debug_flush_ctx_create(TRUE, VMW_DEBUG_FLUSH_STACK); #endif return &vswc->base; out_no_hash: pb_validate_destroy(vswc->validate); out_no_validate: FREE(vswc); return NULL; }
static boolean vmw_svga_winsys_get_cap(struct svga_winsys_screen *sws, SVGA3dDevCapIndex index, SVGA3dDevCapResult *result) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); if (index > vws->ioctl.num_cap_3d || index >= SVGA3D_DEVCAP_MAX || !vws->ioctl.cap_3d[index].has_cap) return FALSE; *result = vws->ioctl.cap_3d[index].result; return TRUE; }
struct svga_winsys_gb_shader * vmw_svga_winsys_shader_create(struct svga_winsys_screen *sws, SVGA3dShaderType type, const uint32 *bytecode, uint32 bytecodeLen) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); struct vmw_svga_winsys_shader *shader; void *code; shader = CALLOC_STRUCT(vmw_svga_winsys_shader); if(!shader) goto out_no_shader; pipe_reference_init(&shader->refcnt, 1); p_atomic_set(&shader->validated, 0); shader->screen = vws; shader->buf = vmw_svga_winsys_buffer_create(sws, 64, SVGA_BUFFER_USAGE_SHADER, bytecodeLen); if (!shader->buf) goto out_no_buf; code = vmw_svga_winsys_buffer_map(sws, shader->buf, PIPE_TRANSFER_WRITE); if (!code) goto out_no_buf; memcpy(code, bytecode, bytecodeLen); vmw_svga_winsys_buffer_unmap(sws, shader->buf); if (!sws->have_vgpu10) { shader->shid = vmw_ioctl_shader_create(vws, type, bytecodeLen); if (shader->shid == SVGA3D_INVALID_ID) goto out_no_shid; } return svga_winsys_shader(shader); out_no_shid: vmw_svga_winsys_buffer_destroy(sws, shader->buf); out_no_buf: FREE(shader); out_no_shader: return NULL; }
static boolean vmw_svga_winsys_surface_can_create(struct svga_winsys_screen *sws, SVGA3dSurfaceFormat format, SVGA3dSize size, uint32 numLayers, uint32 numMipLevels) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); uint32_t buffer_size; buffer_size = svga3dsurface_get_serialized_size(format, size, numMipLevels, numLayers); if (buffer_size > vws->ioctl.max_texture_size) { return FALSE; } return TRUE; }
static struct svga_winsys_buffer * vmw_svga_winsys_buffer_create(struct svga_winsys_screen *sws, unsigned alignment, unsigned usage, unsigned size) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); struct vmw_buffer_desc desc; struct pb_manager *provider; struct pb_buffer *buffer; memset(&desc, 0, sizeof desc); desc.pb_desc.alignment = alignment; desc.pb_desc.usage = usage; if (usage == SVGA_BUFFER_USAGE_PINNED) { if (vws->pools.query_fenced == NULL && !vmw_query_pools_init(vws)) return NULL; provider = vws->pools.query_fenced; } else if (usage == SVGA_BUFFER_USAGE_SHADER) { provider = vws->pools.mob_shader_slab_fenced; } else provider = vws->pools.gmr_fenced; assert(provider); buffer = provider->create_buffer(provider, size, &desc.pb_desc); if(!buffer && provider == vws->pools.gmr_fenced) { assert(provider); provider = vws->pools.gmr_slab_fenced; buffer = provider->create_buffer(provider, size, &desc.pb_desc); } if (!buffer) return NULL; return vmw_svga_winsys_buffer_wrap(buffer); }
static boolean vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, struct svga_winsys_surface *surface, unsigned stride, struct winsys_handle *whandle) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); struct vmw_svga_winsys_surface *vsrf; int ret; if (!surface) return FALSE; vsrf = vmw_svga_winsys_surface(surface); whandle->handle = vsrf->sid; whandle->stride = stride; whandle->offset = 0; switch (whandle->type) { case DRM_API_HANDLE_TYPE_SHARED: case DRM_API_HANDLE_TYPE_KMS: whandle->handle = vsrf->sid; break; case DRM_API_HANDLE_TYPE_FD: ret = drmPrimeHandleToFD(vws->ioctl.drm_fd, vsrf->sid, DRM_CLOEXEC, (int *)&whandle->handle); if (ret) { vmw_error("Failed to get file descriptor from prime.\n"); return FALSE; } break; default: vmw_error("Attempt to export unsupported handle type %d.\n", whandle->type); return FALSE; } return TRUE; }
static struct svga_winsys_buffer * vmw_svga_winsys_buffer_create(struct svga_winsys_screen *sws, unsigned alignment, unsigned usage, unsigned size) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); struct pb_desc desc; struct pb_manager *provider; struct pb_buffer *buffer; memset(&desc, 0, sizeof desc); desc.alignment = alignment; desc.usage = usage; provider = vws->pools.gmr_fenced; assert(provider); buffer = provider->create_buffer(provider, size, &desc); if(!buffer) return NULL; return vmw_svga_winsys_buffer(buffer); }
static boolean vmw_svga_winsys_get_cap(struct svga_winsys_screen *sws, SVGA3dDevCapIndex index, SVGA3dDevCapResult *result) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); const uint32 *capsBlock; const SVGA3dCapsRecord *capsRecord = NULL; uint32 offset; const SVGA3dCapPair *capArray; int numCaps, first, last; if(!vws->ioctl.fifo_map) return FALSE; if(vws->ioctl.fifo_map[SVGA_FIFO_3D_HWVERSION] < SVGA3D_HWVERSION_WS6_B1) return FALSE; /* * Search linearly through the caps block records for the specified type. */ capsBlock = (const uint32 *)&vws->ioctl.fifo_map[SVGA_FIFO_3D_CAPS]; for (offset = 0; capsBlock[offset] != 0; offset += capsBlock[offset]) { const SVGA3dCapsRecord *record; assert(offset < SVGA_FIFO_3D_CAPS_SIZE); record = (const SVGA3dCapsRecord *) (capsBlock + offset); if ((record->header.type >= SVGA3DCAPS_RECORD_DEVCAPS_MIN) && (record->header.type <= SVGA3DCAPS_RECORD_DEVCAPS_MAX) && (!capsRecord || (record->header.type > capsRecord->header.type))) { capsRecord = record; } } if(!capsRecord) return FALSE; /* * Calculate the number of caps from the size of the record. */ capArray = (const SVGA3dCapPair *) capsRecord->data; numCaps = (int) ((capsRecord->header.length * sizeof(uint32) - sizeof capsRecord->header) / (2 * sizeof(uint32))); /* * Binary-search for the cap with the specified index. */ for (first = 0, last = numCaps - 1; first <= last; ) { int mid = (first + last) / 2; if ((SVGA3dDevCapIndex) capArray[mid][0] == index) { /* * Found it. */ result->u = capArray[mid][1]; return TRUE; } /* * Divide and conquer. */ if ((SVGA3dDevCapIndex) capArray[mid][0] > index) { last = mid - 1; } else { first = mid + 1; } } return FALSE; }
/** * vmw_drm_gb_surface_from_handle - Create a shared surface * * @sws: Screen to register the surface with. * @whandle: struct winsys_handle identifying the kernel surface object * @format: On successful return points to a value describing the * surface format. * * Returns a refcounted pointer to a struct svga_winsys_surface * embedded in a struct vmw_svga_winsys_surface on success or NULL * on failure. */ static struct svga_winsys_surface * vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws, struct winsys_handle *whandle, SVGA3dSurfaceFormat *format) { struct vmw_svga_winsys_surface *vsrf; struct svga_winsys_surface *ssrf; struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); SVGA3dSurfaceFlags flags; uint32_t mip_levels; struct vmw_buffer_desc desc; struct pb_manager *provider = vws->pools.gmr; struct pb_buffer *pb_buf; uint32_t handle; int ret; if (whandle->offset != 0) { fprintf(stderr, "Attempt to import unsupported winsys offset %u\n", whandle->offset); return NULL; } ret = vmw_ioctl_gb_surface_ref(vws, whandle, &flags, format, &mip_levels, &handle, &desc.region); if (ret) { fprintf(stderr, "Failed referencing shared surface. SID %d.\n" "Error %d (%s).\n", whandle->handle, ret, strerror(-ret)); return NULL; } if (mip_levels != 1) { fprintf(stderr, "Incorrect number of mipmap levels on shared surface." " SID %d, levels %d\n", whandle->handle, mip_levels); goto out_mip; } vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface); if (!vsrf) goto out_mip; pipe_reference_init(&vsrf->refcnt, 1); p_atomic_set(&vsrf->validated, 0); vsrf->screen = vws; vsrf->sid = handle; vsrf->size = vmw_region_size(desc.region); /* * Synchronize backing buffers of shared surfaces using the * kernel, since we don't pass fence objects around between * processes. */ desc.pb_desc.alignment = 4096; desc.pb_desc.usage = VMW_BUFFER_USAGE_SHARED | VMW_BUFFER_USAGE_SYNC; pb_buf = provider->create_buffer(provider, vsrf->size, &desc.pb_desc); vsrf->buf = vmw_svga_winsys_buffer_wrap(pb_buf); if (!vsrf->buf) goto out_no_buf; ssrf = svga_winsys_surface(vsrf); return ssrf; out_no_buf: FREE(vsrf); out_mip: vmw_ioctl_region_destroy(desc.region); vmw_ioctl_surface_destroy(vws, whandle->handle); return NULL; }
static struct svga_winsys_surface * vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, struct winsys_handle *whandle, SVGA3dSurfaceFormat *format) { struct vmw_svga_winsys_surface *vsrf; struct svga_winsys_surface *ssrf; struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); union drm_vmw_surface_reference_arg arg; struct drm_vmw_surface_arg *req = &arg.req; struct drm_vmw_surface_create_req *rep = &arg.rep; uint32_t handle = 0; struct drm_vmw_size size; SVGA3dSize base_size; int ret; int i; if (whandle->offset != 0) { fprintf(stderr, "Attempt to import unsupported winsys offset %u\n", whandle->offset); return NULL; } switch (whandle->type) { case DRM_API_HANDLE_TYPE_SHARED: case DRM_API_HANDLE_TYPE_KMS: handle = whandle->handle; break; case DRM_API_HANDLE_TYPE_FD: ret = drmPrimeFDToHandle(vws->ioctl.drm_fd, whandle->handle, &handle); if (ret) { vmw_error("Failed to get handle from prime fd %d.\n", (int) whandle->handle); return NULL; } break; default: vmw_error("Attempt to import unsupported handle type %d.\n", whandle->type); return NULL; } memset(&arg, 0, sizeof(arg)); req->sid = handle; rep->size_addr = (unsigned long)&size; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE, &arg, sizeof(arg)); /* * Need to close the handle we got from prime. */ if (whandle->type == DRM_API_HANDLE_TYPE_FD) vmw_ioctl_surface_destroy(vws, handle); if (ret) { /* * Any attempt to share something other than a surface, like a dumb * kms buffer, should fail here. */ vmw_error("Failed referencing shared surface. SID %d.\n" "Error %d (%s).\n", handle, ret, strerror(-ret)); return NULL; } if (rep->mip_levels[0] != 1) { vmw_error("Incorrect number of mipmap levels on shared surface." " SID %d, levels %d\n", handle, rep->mip_levels[0]); goto out_mip; } for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { if (rep->mip_levels[i] != 0) { vmw_error("Incorrect number of faces levels on shared surface." " SID %d, face %d present.\n", handle, i); goto out_mip; } } vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface); if (!vsrf) goto out_mip; pipe_reference_init(&vsrf->refcnt, 1); p_atomic_set(&vsrf->validated, 0); vsrf->screen = vws; vsrf->sid = handle; ssrf = svga_winsys_surface(vsrf); *format = rep->format; /* Estimate usage, for early flushing. */ base_size.width = size.width; base_size.height = size.height; base_size.depth = size.depth; vsrf->size = svga3dsurface_get_serialized_size(rep->format, base_size, rep->mip_levels[0], FALSE); return ssrf; out_mip: vmw_ioctl_surface_destroy(vws, handle); return NULL; }
static struct pipe_buffer * vmw_drm_buffer_from_handle(struct drm_api *drm_api, struct pipe_screen *screen, const char *name, unsigned handle) { struct vmw_svga_winsys_surface *vsrf; struct svga_winsys_surface *ssrf; struct vmw_winsys_screen *vws = vmw_winsys_screen(svga_winsys_screen(screen)); struct pipe_buffer *buf; union drm_vmw_surface_reference_arg arg; struct drm_vmw_surface_arg *req = &arg.req; struct drm_vmw_surface_create_req *rep = &arg.rep; int ret; int i; /** * The vmware device specific handle is the hardware SID. * FIXME: We probably want to move this to the ioctl implementations. */ memset(&arg, 0, sizeof(arg)); req->sid = handle; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE, &arg, sizeof(arg)); if (ret) { fprintf(stderr, "Failed referencing shared surface. SID %d.\n" "Error %d (%s).\n", handle, ret, strerror(-ret)); return NULL; } if (rep->mip_levels[0] != 1) { fprintf(stderr, "Incorrect number of mipmap levels on shared surface." " SID %d, levels %d\n", handle, rep->mip_levels[0]); goto out_mip; } for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { if (rep->mip_levels[i] != 0) { fprintf(stderr, "Incorrect number of faces levels on shared surface." " SID %d, face %d present.\n", handle, i); goto out_mip; } } vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface); if (!vsrf) goto out_mip; pipe_reference_init(&vsrf->refcnt, 1); p_atomic_set(&vsrf->validated, 0); vsrf->sid = handle; ssrf = svga_winsys_surface(vsrf); buf = svga_screen_buffer_wrap_surface(screen, rep->format, ssrf); if (!buf) vmw_svga_winsys_surface_reference(&vsrf, NULL); return buf; out_mip: vmw_ioctl_surface_destroy(vws, handle); return NULL; }
static struct svga_winsys_surface * vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws, SVGA3dSurfaceFlags flags, SVGA3dSurfaceFormat format, unsigned usage, SVGA3dSize size, uint32 numLayers, uint32 numMipLevels, unsigned sampleCount) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); struct vmw_svga_winsys_surface *surface; struct vmw_buffer_desc desc; struct pb_manager *provider; uint32_t buffer_size; memset(&desc, 0, sizeof(desc)); surface = CALLOC_STRUCT(vmw_svga_winsys_surface); if(!surface) goto no_surface; pipe_reference_init(&surface->refcnt, 1); p_atomic_set(&surface->validated, 0); surface->screen = vws; pipe_mutex_init(surface->mutex); surface->shared = !!(usage & SVGA_SURFACE_USAGE_SHARED); provider = (surface->shared) ? vws->pools.gmr : vws->pools.mob_fenced; /* * Used for the backing buffer GB surfaces, and to approximate * when to flush on non-GB hosts. */ buffer_size = svga3dsurface_get_serialized_size(format, size, numMipLevels, numLayers); if (flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) buffer_size += sizeof(SVGA3dDXSOState); if (buffer_size > vws->ioctl.max_texture_size) { goto no_sid; } if (sws->have_gb_objects) { SVGAGuestPtr ptr = {0,0}; /* * If the backing buffer size is small enough, try to allocate a * buffer out of the buffer cache. Otherwise, let the kernel allocate * a suitable buffer for us. */ if (buffer_size < VMW_TRY_CACHED_SIZE && !surface->shared) { struct pb_buffer *pb_buf; surface->size = buffer_size; desc.pb_desc.alignment = 4096; desc.pb_desc.usage = 0; pb_buf = provider->create_buffer(provider, buffer_size, &desc.pb_desc); surface->buf = vmw_svga_winsys_buffer_wrap(pb_buf); if (surface->buf && !vmw_gmr_bufmgr_region_ptr(pb_buf, &ptr)) assert(0); } surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage, size, numLayers, numMipLevels, sampleCount, ptr.gmrId, surface->buf ? NULL : &desc.region); if (surface->sid == SVGA3D_INVALID_ID && surface->buf) { /* * Kernel refused to allocate a surface for us. * Perhaps something was wrong with our buffer? * This is really a guard against future new size requirements * on the backing buffers. */ vmw_svga_winsys_buffer_destroy(sws, surface->buf); surface->buf = NULL; surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage, size, numLayers, numMipLevels, sampleCount, 0, &desc.region); if (surface->sid == SVGA3D_INVALID_ID) goto no_sid; } /* * If the kernel created the buffer for us, wrap it into a * vmw_svga_winsys_buffer. */ if (surface->buf == NULL) { struct pb_buffer *pb_buf; surface->size = vmw_region_size(desc.region); desc.pb_desc.alignment = 4096; desc.pb_desc.usage = VMW_BUFFER_USAGE_SHARED; pb_buf = provider->create_buffer(provider, surface->size, &desc.pb_desc); surface->buf = vmw_svga_winsys_buffer_wrap(pb_buf); if (surface->buf == NULL) { vmw_ioctl_region_destroy(desc.region); vmw_ioctl_surface_destroy(vws, surface->sid); goto no_sid; } } } else { surface->sid = vmw_ioctl_surface_create(vws, flags, format, usage, size, numLayers, numMipLevels, sampleCount); if(surface->sid == SVGA3D_INVALID_ID) goto no_sid; /* Best estimate for surface size, used for early flushing. */ surface->size = buffer_size; surface->buf = NULL; } return svga_winsys_surface(surface); no_sid: if (surface->buf) vmw_svga_winsys_buffer_destroy(sws, surface->buf); FREE(surface); no_surface: return NULL; }