Path: blob/21.2-virgl/src/gallium/winsys/svga/drm/vmw_context.c
4573 views
/**********************************************************1* Copyright 2009-2015 VMware, Inc. All rights reserved.2*3* Permission is hereby granted, free of charge, to any person4* obtaining a copy of this software and associated documentation5* files (the "Software"), to deal in the Software without6* restriction, including without limitation the rights to use, copy,7* modify, merge, publish, distribute, sublicense, and/or sell copies8* of the Software, and to permit persons to whom the Software is9* furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23**********************************************************/242526#include "svga_cmd.h"2728#include "util/u_debug.h"29#include "util/u_memory.h"30#include "util/u_debug_stack.h"31#include "util/u_debug_flush.h"32#include "util/u_hash_table.h"33#include "pipebuffer/pb_buffer.h"34#include "pipebuffer/pb_validate.h"3536#include "svga_winsys.h"37#include "vmw_context.h"38#include "vmw_screen.h"39#include "vmw_buffer.h"40#include "vmw_surface.h"41#include "vmw_fence.h"42#include "vmw_shader.h"43#include "vmw_query.h"4445#define VMW_COMMAND_SIZE (64*1024)46#define VMW_SURFACE_RELOCS (1024)47#define VMW_SHADER_RELOCS (1024)48#define VMW_REGION_RELOCS (512)4950#define VMW_MUST_FLUSH_STACK 85152/*53* A factor applied to the maximum mob memory size to determine54* the optimial time to preemptively flush the command buffer.55* The constant is based on some performance trials with SpecViewperf.56*/57#define VMW_MAX_MOB_MEM_FACTOR 25859/*60* A factor applied to the maximum surface memory size to determine61* the optimial time to preemptively flush the command buffer.62* The constant is based on some performance trials with SpecViewperf.63*/64#define VMW_MAX_SURF_MEM_FACTOR 265666768struct vmw_buffer_relocation69{70struct pb_buffer *buffer;71boolean is_mob;72uint32 offset;7374union {75struct {76struct SVGAGuestPtr *where;77} region;78struct {79SVGAMobId *id;80uint32 *offset_into_mob;81} mob;82};83};8485struct vmw_ctx_validate_item {86union {87struct vmw_svga_winsys_surface *vsurf;88struct vmw_svga_winsys_shader *vshader;89};90boolean referenced;91};9293struct vmw_svga_winsys_context94{95struct svga_winsys_context base;9697struct vmw_winsys_screen *vws;98struct hash_table *hash;99100#ifdef DEBUG101boolean must_flush;102struct debug_stack_frame must_flush_stack[VMW_MUST_FLUSH_STACK];103struct debug_flush_ctx *fctx;104#endif105106struct {107uint8_t buffer[VMW_COMMAND_SIZE];108uint32_t size;109uint32_t used;110uint32_t reserved;111} command;112113struct {114struct vmw_ctx_validate_item items[VMW_SURFACE_RELOCS];115uint32_t size;116uint32_t used;117uint32_t staged;118uint32_t reserved;119} surface;120121struct {122struct vmw_buffer_relocation relocs[VMW_REGION_RELOCS];123uint32_t size;124uint32_t used;125uint32_t staged;126uint32_t reserved;127} region;128129struct {130struct vmw_ctx_validate_item items[VMW_SHADER_RELOCS];131uint32_t size;132uint32_t used;133uint32_t staged;134uint32_t reserved;135} shader;136137struct pb_validate *validate;138139/**140* The amount of surface, GMR or MOB memory that is referred by the commands141* currently batched in the context command buffer.142*/143uint64_t seen_surfaces;144uint64_t seen_regions;145uint64_t seen_mobs;146147/**148* Whether this context should fail to reserve more commands, not because it149* ran out of command space, but because a substantial ammount of GMR was150* referred.151*/152boolean preemptive_flush;153};154155156static inline struct vmw_svga_winsys_context *157vmw_svga_winsys_context(struct svga_winsys_context *swc)158{159assert(swc);160return (struct vmw_svga_winsys_context *)swc;161}162163164static inline enum pb_usage_flags165vmw_translate_to_pb_flags(unsigned flags)166{167enum pb_usage_flags f = 0;168if (flags & SVGA_RELOC_READ)169f |= PB_USAGE_GPU_READ;170171if (flags & SVGA_RELOC_WRITE)172f |= PB_USAGE_GPU_WRITE;173174return f;175}176177static enum pipe_error178vmw_swc_flush(struct svga_winsys_context *swc,179struct pipe_fence_handle **pfence)180{181struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);182struct vmw_winsys_screen *vws = vswc->vws;183struct pipe_fence_handle *fence = NULL;184unsigned i;185enum pipe_error ret;186187/*188* If we hit a retry, lock the mutex and retry immediately.189* If we then still hit a retry, sleep until another thread190* wakes us up after it has released its buffers from the191* validate list.192*193* If we hit another error condition, we still need to broadcast since194* pb_validate_validate releases validated buffers in its error path.195*/196197ret = pb_validate_validate(vswc->validate);198if (ret != PIPE_OK) {199mtx_lock(&vws->cs_mutex);200while (ret == PIPE_ERROR_RETRY) {201ret = pb_validate_validate(vswc->validate);202if (ret == PIPE_ERROR_RETRY) {203cnd_wait(&vws->cs_cond, &vws->cs_mutex);204}205}206if (ret != PIPE_OK) {207cnd_broadcast(&vws->cs_cond);208}209mtx_unlock(&vws->cs_mutex);210}211212assert(ret == PIPE_OK);213if(ret == PIPE_OK) {214215/* Apply relocations */216for(i = 0; i < vswc->region.used; ++i) {217struct vmw_buffer_relocation *reloc = &vswc->region.relocs[i];218struct SVGAGuestPtr ptr;219220if(!vmw_gmr_bufmgr_region_ptr(reloc->buffer, &ptr))221assert(0);222223ptr.offset += reloc->offset;224225if (reloc->is_mob) {226if (reloc->mob.id)227*reloc->mob.id = ptr.gmrId;228if (reloc->mob.offset_into_mob)229*reloc->mob.offset_into_mob = ptr.offset;230else {231assert(ptr.offset == 0);232}233} else234*reloc->region.where = ptr;235}236237if (vswc->command.used || pfence != NULL)238vmw_ioctl_command(vws,239vswc->base.cid,2400,241vswc->command.buffer,242vswc->command.used,243&fence,244vswc->base.imported_fence_fd,245vswc->base.hints);246247pb_validate_fence(vswc->validate, fence);248mtx_lock(&vws->cs_mutex);249cnd_broadcast(&vws->cs_cond);250mtx_unlock(&vws->cs_mutex);251}252253vswc->command.used = 0;254vswc->command.reserved = 0;255256for(i = 0; i < vswc->surface.used + vswc->surface.staged; ++i) {257struct vmw_ctx_validate_item *isurf = &vswc->surface.items[i];258if (isurf->referenced)259p_atomic_dec(&isurf->vsurf->validated);260vmw_svga_winsys_surface_reference(&isurf->vsurf, NULL);261}262263_mesa_hash_table_clear(vswc->hash, NULL);264vswc->surface.used = 0;265vswc->surface.reserved = 0;266267for(i = 0; i < vswc->shader.used + vswc->shader.staged; ++i) {268struct vmw_ctx_validate_item *ishader = &vswc->shader.items[i];269if (ishader->referenced)270p_atomic_dec(&ishader->vshader->validated);271vmw_svga_winsys_shader_reference(&ishader->vshader, NULL);272}273274vswc->shader.used = 0;275vswc->shader.reserved = 0;276277vswc->region.used = 0;278vswc->region.reserved = 0;279280#ifdef DEBUG281vswc->must_flush = FALSE;282debug_flush_flush(vswc->fctx);283#endif284swc->hints &= ~SVGA_HINT_FLAG_CAN_PRE_FLUSH;285swc->hints &= ~SVGA_HINT_FLAG_EXPORT_FENCE_FD;286vswc->preemptive_flush = FALSE;287vswc->seen_surfaces = 0;288vswc->seen_regions = 0;289vswc->seen_mobs = 0;290291if (vswc->base.imported_fence_fd != -1) {292close(vswc->base.imported_fence_fd);293vswc->base.imported_fence_fd = -1;294}295296if(pfence)297vmw_fence_reference(vswc->vws, pfence, fence);298299vmw_fence_reference(vswc->vws, &fence, NULL);300301return ret;302}303304305static void *306vmw_swc_reserve(struct svga_winsys_context *swc,307uint32_t nr_bytes, uint32_t nr_relocs )308{309struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);310311#ifdef DEBUG312/* Check if somebody forgot to check the previous failure */313if(vswc->must_flush) {314debug_printf("Forgot to flush:\n");315debug_backtrace_dump(vswc->must_flush_stack, VMW_MUST_FLUSH_STACK);316assert(!vswc->must_flush);317}318debug_flush_might_flush(vswc->fctx);319#endif320321assert(nr_bytes <= vswc->command.size);322if(nr_bytes > vswc->command.size)323return NULL;324325if(vswc->preemptive_flush ||326vswc->command.used + nr_bytes > vswc->command.size ||327vswc->surface.used + nr_relocs > vswc->surface.size ||328vswc->shader.used + nr_relocs > vswc->shader.size ||329vswc->region.used + nr_relocs > vswc->region.size) {330#ifdef DEBUG331vswc->must_flush = TRUE;332debug_backtrace_capture(vswc->must_flush_stack, 1,333VMW_MUST_FLUSH_STACK);334#endif335return NULL;336}337338assert(vswc->command.used + nr_bytes <= vswc->command.size);339assert(vswc->surface.used + nr_relocs <= vswc->surface.size);340assert(vswc->shader.used + nr_relocs <= vswc->shader.size);341assert(vswc->region.used + nr_relocs <= vswc->region.size);342343vswc->command.reserved = nr_bytes;344vswc->surface.reserved = nr_relocs;345vswc->surface.staged = 0;346vswc->shader.reserved = nr_relocs;347vswc->shader.staged = 0;348vswc->region.reserved = nr_relocs;349vswc->region.staged = 0;350351return vswc->command.buffer + vswc->command.used;352}353354static unsigned355vmw_swc_get_command_buffer_size(struct svga_winsys_context *swc)356{357const struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);358return vswc->command.used;359}360361static void362vmw_swc_context_relocation(struct svga_winsys_context *swc,363uint32 *cid)364{365*cid = swc->cid;366}367368static boolean369vmw_swc_add_validate_buffer(struct vmw_svga_winsys_context *vswc,370struct pb_buffer *pb_buf,371unsigned flags)372{373ASSERTED enum pipe_error ret;374unsigned translated_flags;375boolean already_present;376377translated_flags = vmw_translate_to_pb_flags(flags);378ret = pb_validate_add_buffer(vswc->validate, pb_buf, translated_flags,379vswc->hash, &already_present);380assert(ret == PIPE_OK);381return !already_present;382}383384static void385vmw_swc_region_relocation(struct svga_winsys_context *swc,386struct SVGAGuestPtr *where,387struct svga_winsys_buffer *buffer,388uint32 offset,389unsigned flags)390{391struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);392struct vmw_buffer_relocation *reloc;393394assert(vswc->region.staged < vswc->region.reserved);395396reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged];397reloc->region.where = where;398399/*400* pb_validate holds a refcount to the buffer, so no need to401* refcount it again in the relocation.402*/403reloc->buffer = vmw_pb_buffer(buffer);404reloc->offset = offset;405reloc->is_mob = FALSE;406++vswc->region.staged;407408if (vmw_swc_add_validate_buffer(vswc, reloc->buffer, flags)) {409vswc->seen_regions += reloc->buffer->size;410if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&411vswc->seen_regions >= VMW_GMR_POOL_SIZE/5)412vswc->preemptive_flush = TRUE;413}414415#ifdef DEBUG416if (!(flags & SVGA_RELOC_INTERNAL))417debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer));418#endif419}420421static void422vmw_swc_mob_relocation(struct svga_winsys_context *swc,423SVGAMobId *id,424uint32 *offset_into_mob,425struct svga_winsys_buffer *buffer,426uint32 offset,427unsigned flags)428{429struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);430struct vmw_buffer_relocation *reloc;431struct pb_buffer *pb_buffer = vmw_pb_buffer(buffer);432433if (id) {434assert(vswc->region.staged < vswc->region.reserved);435436reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged];437reloc->mob.id = id;438reloc->mob.offset_into_mob = offset_into_mob;439440/*441* pb_validate holds a refcount to the buffer, so no need to442* refcount it again in the relocation.443*/444reloc->buffer = pb_buffer;445reloc->offset = offset;446reloc->is_mob = TRUE;447++vswc->region.staged;448}449450if (vmw_swc_add_validate_buffer(vswc, pb_buffer, flags)) {451vswc->seen_mobs += pb_buffer->size;452453if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&454vswc->seen_mobs >=455vswc->vws->ioctl.max_mob_memory / VMW_MAX_MOB_MEM_FACTOR)456vswc->preemptive_flush = TRUE;457}458459#ifdef DEBUG460if (!(flags & SVGA_RELOC_INTERNAL))461debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer));462#endif463}464465466/**467* vmw_swc_surface_clear_reference - Clear referenced info for a surface468*469* @swc: Pointer to an svga_winsys_context470* @vsurf: Pointer to a vmw_svga_winsys_surface, the referenced info of which471* we want to clear472*473* This is primarily used by a discard surface map to indicate that the474* surface data is no longer referenced by a draw call, and mapping it475* should therefore no longer cause a flush.476*/477void478vmw_swc_surface_clear_reference(struct svga_winsys_context *swc,479struct vmw_svga_winsys_surface *vsurf)480{481struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);482struct vmw_ctx_validate_item *isrf =483util_hash_table_get(vswc->hash, vsurf);484485if (isrf && isrf->referenced) {486isrf->referenced = FALSE;487p_atomic_dec(&vsurf->validated);488}489}490491static void492vmw_swc_surface_only_relocation(struct svga_winsys_context *swc,493uint32 *where,494struct vmw_svga_winsys_surface *vsurf,495unsigned flags)496{497struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);498struct vmw_ctx_validate_item *isrf;499500assert(vswc->surface.staged < vswc->surface.reserved);501isrf = util_hash_table_get(vswc->hash, vsurf);502503if (isrf == NULL) {504isrf = &vswc->surface.items[vswc->surface.used + vswc->surface.staged];505vmw_svga_winsys_surface_reference(&isrf->vsurf, vsurf);506isrf->referenced = FALSE;507508_mesa_hash_table_insert(vswc->hash, vsurf, isrf);509++vswc->surface.staged;510511vswc->seen_surfaces += vsurf->size;512if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&513vswc->seen_surfaces >=514vswc->vws->ioctl.max_surface_memory / VMW_MAX_SURF_MEM_FACTOR)515vswc->preemptive_flush = TRUE;516}517518if (!(flags & SVGA_RELOC_INTERNAL) && !isrf->referenced) {519isrf->referenced = TRUE;520p_atomic_inc(&vsurf->validated);521}522523if (where)524*where = vsurf->sid;525}526527static void528vmw_swc_surface_relocation(struct svga_winsys_context *swc,529uint32 *where,530uint32 *mobid,531struct svga_winsys_surface *surface,532unsigned flags)533{534struct vmw_svga_winsys_surface *vsurf;535536assert(swc->have_gb_objects || mobid == NULL);537538if (!surface) {539*where = SVGA3D_INVALID_ID;540if (mobid)541*mobid = SVGA3D_INVALID_ID;542return;543}544545vsurf = vmw_svga_winsys_surface(surface);546vmw_swc_surface_only_relocation(swc, where, vsurf, flags);547548if (swc->have_gb_objects && vsurf->buf != NULL) {549550/*551* Make sure backup buffer ends up fenced.552*/553554mtx_lock(&vsurf->mutex);555assert(vsurf->buf != NULL);556557/*558* An internal reloc means that the surface transfer direction559* is opposite to the MOB transfer direction...560*/561if ((flags & SVGA_RELOC_INTERNAL) &&562(flags & (SVGA_RELOC_READ | SVGA_RELOC_WRITE)) !=563(SVGA_RELOC_READ | SVGA_RELOC_WRITE))564flags ^= (SVGA_RELOC_READ | SVGA_RELOC_WRITE);565vmw_swc_mob_relocation(swc, mobid, NULL, (struct svga_winsys_buffer *)566vsurf->buf, 0, flags);567mtx_unlock(&vsurf->mutex);568}569}570571static void572vmw_swc_shader_relocation(struct svga_winsys_context *swc,573uint32 *shid,574uint32 *mobid,575uint32 *offset,576struct svga_winsys_gb_shader *shader,577unsigned flags)578{579struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);580struct vmw_winsys_screen *vws = vswc->vws;581struct vmw_svga_winsys_shader *vshader;582struct vmw_ctx_validate_item *ishader;583584if(!shader) {585*shid = SVGA3D_INVALID_ID;586return;587}588589vshader = vmw_svga_winsys_shader(shader);590591if (!vws->base.have_vgpu10) {592assert(vswc->shader.staged < vswc->shader.reserved);593ishader = util_hash_table_get(vswc->hash, vshader);594595if (ishader == NULL) {596ishader = &vswc->shader.items[vswc->shader.used + vswc->shader.staged];597vmw_svga_winsys_shader_reference(&ishader->vshader, vshader);598ishader->referenced = FALSE;599600_mesa_hash_table_insert(vswc->hash, vshader, ishader);601++vswc->shader.staged;602}603604if (!ishader->referenced) {605ishader->referenced = TRUE;606p_atomic_inc(&vshader->validated);607}608}609610if (shid)611*shid = vshader->shid;612613if (vshader->buf)614vmw_swc_mob_relocation(swc, mobid, offset, vshader->buf,6150, SVGA_RELOC_READ);616}617618static void619vmw_swc_query_relocation(struct svga_winsys_context *swc,620SVGAMobId *id,621struct svga_winsys_gb_query *query)622{623/* Queries are backed by one big MOB */624vmw_swc_mob_relocation(swc, id, NULL, query->buf, 0,625SVGA_RELOC_READ | SVGA_RELOC_WRITE);626}627628static void629vmw_swc_commit(struct svga_winsys_context *swc)630{631struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);632633assert(vswc->command.used + vswc->command.reserved <= vswc->command.size);634vswc->command.used += vswc->command.reserved;635vswc->command.reserved = 0;636637assert(vswc->surface.staged <= vswc->surface.reserved);638assert(vswc->surface.used + vswc->surface.staged <= vswc->surface.size);639vswc->surface.used += vswc->surface.staged;640vswc->surface.staged = 0;641vswc->surface.reserved = 0;642643assert(vswc->shader.staged <= vswc->shader.reserved);644assert(vswc->shader.used + vswc->shader.staged <= vswc->shader.size);645vswc->shader.used += vswc->shader.staged;646vswc->shader.staged = 0;647vswc->shader.reserved = 0;648649assert(vswc->region.staged <= vswc->region.reserved);650assert(vswc->region.used + vswc->region.staged <= vswc->region.size);651vswc->region.used += vswc->region.staged;652vswc->region.staged = 0;653vswc->region.reserved = 0;654}655656657static void658vmw_swc_destroy(struct svga_winsys_context *swc)659{660struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);661unsigned i;662663for(i = 0; i < vswc->surface.used; ++i) {664struct vmw_ctx_validate_item *isurf = &vswc->surface.items[i];665if (isurf->referenced)666p_atomic_dec(&isurf->vsurf->validated);667vmw_svga_winsys_surface_reference(&isurf->vsurf, NULL);668}669670for(i = 0; i < vswc->shader.used; ++i) {671struct vmw_ctx_validate_item *ishader = &vswc->shader.items[i];672if (ishader->referenced)673p_atomic_dec(&ishader->vshader->validated);674vmw_svga_winsys_shader_reference(&ishader->vshader, NULL);675}676677_mesa_hash_table_destroy(vswc->hash, NULL);678pb_validate_destroy(vswc->validate);679vmw_ioctl_context_destroy(vswc->vws, swc->cid);680#ifdef DEBUG681debug_flush_ctx_destroy(vswc->fctx);682#endif683FREE(vswc);684}685686/**687* vmw_svga_winsys_vgpu10_shader_screate - The winsys shader_crate callback688*689* @swc: The winsys context.690* @shaderId: Previously allocated shader id.691* @shaderType: The shader type.692* @bytecode: The shader bytecode693* @bytecodelen: The length of the bytecode.694*695* Creates an svga_winsys_gb_shader structure and allocates a buffer for the696* shader code and copies the shader code into the buffer. Shader697* resource creation is not done.698*/699static struct svga_winsys_gb_shader *700vmw_svga_winsys_vgpu10_shader_create(struct svga_winsys_context *swc,701uint32 shaderId,702SVGA3dShaderType shaderType,703const uint32 *bytecode,704uint32 bytecodeLen,705const SVGA3dDXShaderSignatureHeader *sgnInfo,706uint32 sgnLen)707{708struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);709struct vmw_svga_winsys_shader *shader;710shader = vmw_svga_shader_create(&vswc->vws->base, shaderType, bytecode,711bytecodeLen, sgnInfo, sgnLen);712if (!shader)713return NULL;714715shader->shid = shaderId;716return svga_winsys_shader(shader);717}718719/**720* vmw_svga_winsys_vgpu10_shader_destroy - The winsys shader_destroy callback.721*722* @swc: The winsys context.723* @shader: A shader structure previously allocated by shader_create.724*725* Frees the shader structure and the buffer holding the shader code.726*/727static void728vmw_svga_winsys_vgpu10_shader_destroy(struct svga_winsys_context *swc,729struct svga_winsys_gb_shader *shader)730{731struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);732733vmw_svga_winsys_shader_destroy(&vswc->vws->base, shader);734}735736/**737* vmw_svga_winsys_resource_rebind - The winsys resource_rebind callback738*739* @swc: The winsys context.740* @surface: The surface to be referenced.741* @shader: The shader to be referenced.742* @flags: Relocation flags.743*744* This callback is needed because shader backing buffers are sub-allocated, and745* hence the kernel fencing is not sufficient. The buffers need to be put on746* the context's validation list and fenced after command submission to avoid747* reuse of busy shader buffers. In addition, surfaces need to be put on the748* validation list in order for the driver to regard them as referenced749* by the command stream.750*/751static enum pipe_error752vmw_svga_winsys_resource_rebind(struct svga_winsys_context *swc,753struct svga_winsys_surface *surface,754struct svga_winsys_gb_shader *shader,755unsigned flags)756{757/**758* Need to reserve one validation item for either the surface or759* the shader.760*/761if (!vmw_swc_reserve(swc, 0, 1))762return PIPE_ERROR_OUT_OF_MEMORY;763764if (surface)765vmw_swc_surface_relocation(swc, NULL, NULL, surface, flags);766else if (shader)767vmw_swc_shader_relocation(swc, NULL, NULL, NULL, shader, flags);768769vmw_swc_commit(swc);770771return PIPE_OK;772}773774struct svga_winsys_context *775vmw_svga_winsys_context_create(struct svga_winsys_screen *sws)776{777struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);778struct vmw_svga_winsys_context *vswc;779780vswc = CALLOC_STRUCT(vmw_svga_winsys_context);781if(!vswc)782return NULL;783784vswc->base.destroy = vmw_swc_destroy;785vswc->base.reserve = vmw_swc_reserve;786vswc->base.get_command_buffer_size = vmw_swc_get_command_buffer_size;787vswc->base.surface_relocation = vmw_swc_surface_relocation;788vswc->base.region_relocation = vmw_swc_region_relocation;789vswc->base.mob_relocation = vmw_swc_mob_relocation;790vswc->base.query_relocation = vmw_swc_query_relocation;791vswc->base.query_bind = vmw_swc_query_bind;792vswc->base.context_relocation = vmw_swc_context_relocation;793vswc->base.shader_relocation = vmw_swc_shader_relocation;794vswc->base.commit = vmw_swc_commit;795vswc->base.flush = vmw_swc_flush;796vswc->base.surface_map = vmw_svga_winsys_surface_map;797vswc->base.surface_unmap = vmw_svga_winsys_surface_unmap;798799vswc->base.shader_create = vmw_svga_winsys_vgpu10_shader_create;800vswc->base.shader_destroy = vmw_svga_winsys_vgpu10_shader_destroy;801802vswc->base.resource_rebind = vmw_svga_winsys_resource_rebind;803804if (sws->have_vgpu10)805vswc->base.cid = vmw_ioctl_extended_context_create(vws, sws->have_vgpu10);806else807vswc->base.cid = vmw_ioctl_context_create(vws);808809if (vswc->base.cid == -1)810goto out_no_context;811812vswc->base.imported_fence_fd = -1;813814vswc->base.have_gb_objects = sws->have_gb_objects;815816vswc->vws = vws;817818vswc->command.size = VMW_COMMAND_SIZE;819vswc->surface.size = VMW_SURFACE_RELOCS;820vswc->shader.size = VMW_SHADER_RELOCS;821vswc->region.size = VMW_REGION_RELOCS;822823vswc->validate = pb_validate_create();824if(!vswc->validate)825goto out_no_validate;826827vswc->hash = util_hash_table_create_ptr_keys();828if (!vswc->hash)829goto out_no_hash;830831#ifdef DEBUG832vswc->fctx = debug_flush_ctx_create(TRUE, VMW_DEBUG_FLUSH_STACK);833#endif834835vswc->base.force_coherent = vws->force_coherent;836return &vswc->base;837838out_no_hash:839pb_validate_destroy(vswc->validate);840out_no_validate:841vmw_ioctl_context_destroy(vws, vswc->base.cid);842out_no_context:843FREE(vswc);844return NULL;845}846847848