From e6df0acad91d273e346b01bdc6451f44bfb72653 Mon Sep 17 00:00:00 2001 From: Quantum Date: Fri, 27 Aug 2021 00:27:16 -0400 Subject: [PATCH] [common] vector: eliminate double allocation when possible This commit creates two constructor/destructor pairs for vector: * vector_alloc/vector_free dynamically allocates the vector itself * vector_create/vector_destroy uses existing Vector objects --- client/renderers/EGL/postprocess.c | 26 +++++++---------- client/renderers/EGL/texture_dmabuf.c | 17 ++++++----- common/include/common/vector.h | 7 ++++- common/src/platform/windows/ivshmem.c | 14 ++++----- common/src/vector.c | 41 +++++++++++++++++++-------- 5 files changed, 61 insertions(+), 44 deletions(-) diff --git a/client/renderers/EGL/postprocess.c b/client/renderers/EGL/postprocess.c index f133aaa4..111637e2 100644 --- a/client/renderers/EGL/postprocess.c +++ b/client/renderers/EGL/postprocess.c @@ -38,7 +38,7 @@ static const EGL_FilterOps * EGL_Filters[] = struct EGL_PostProcess { - Vector * filters; + Vector filters; GLuint output; unsigned int outputX, outputY; _Atomic(bool) modified; @@ -74,8 +74,8 @@ static void configUI(void * opaque, int * id) igGetWindowPos(&window); igGetMousePos(&pos); - EGL_Filter ** filters = vector_data(this->filters); - size_t count = vector_size(this->filters); + EGL_Filter ** filters = vector_data(&this->filters); + size_t count = vector_size(&this->filters); for (size_t i = 0; i < count; ++i) { EGL_Filter * filter = filters[i]; @@ -144,8 +144,7 @@ bool egl_postProcessInit(EGL_PostProcess ** pp) return false; } - this->filters = vector_create(sizeof(EGL_Filter *), ARRAY_LENGTH(EGL_Filters)); - if (!this->filters) + if (!vector_create(&this->filters, sizeof(EGL_Filter *), ARRAY_LENGTH(EGL_Filters))) { DEBUG_ERROR("Failed to allocate the filter list"); goto error_this; @@ -164,7 +163,7 @@ bool egl_postProcessInit(EGL_PostProcess ** pp) return true; error_filters: - vector_free(this->filters); + vector_destroy(&this->filters); error_this: free(this); @@ -178,13 +177,10 @@ void egl_postProcessFree(EGL_PostProcess ** pp) EGL_PostProcess * this = *pp; - if (this->filters) - { - EGL_Filter ** filter; - vector_forEachRef(filter, this->filters) - egl_filterFree(filter); - vector_free(this->filters); - } + EGL_Filter ** filter; + vector_forEachRef(filter, &this->filters) + egl_filterFree(filter); + vector_destroy(&this->filters); egl_modelFree(&this->model); free(this); @@ -197,7 +193,7 @@ bool egl_postProcessAdd(EGL_PostProcess * this, const EGL_FilterOps * ops) if (!egl_filterInit(ops, &filter)) return false; - vector_push(this->filters, &filter); + vector_push(&this->filters, &filter); return true; } @@ -219,7 +215,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, atomic_store(&this->modified, false); EGL_Filter * filter; - vector_forEach(filter, this->filters) + vector_forEach(filter, &this->filters) { egl_filterSetOutputResHint(filter, targetX, targetY); egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY); diff --git a/client/renderers/EGL/texture_dmabuf.c b/client/renderers/EGL/texture_dmabuf.c index 575ce92f..84333c4a 100644 --- a/client/renderers/EGL/texture_dmabuf.c +++ b/client/renderers/EGL/texture_dmabuf.c @@ -36,7 +36,7 @@ typedef struct TexDMABUF TextureBuffer base; EGLDisplay display; - Vector * images; + Vector images; } TexDMABUF; @@ -47,9 +47,9 @@ EGL_TextureOps EGL_TextureDMABUF; static void egl_texDMABUFCleanup(TexDMABUF * this) { struct FdImage * image; - vector_forEachRef(image, this->images) + vector_forEachRef(image, &this->images) eglDestroyImage(this->display, image->image); - vector_clear(this->images); + vector_clear(&this->images); } // dmabuf functions @@ -59,8 +59,7 @@ static bool egl_texDMABUFInit(EGL_Texture ** texture, EGLDisplay * display) TexDMABUF * this = calloc(1, sizeof(*this)); *texture = &this->base.base; - this->images = vector_create(sizeof(struct FdImage), 2); - if (!this->images) + if (!vector_create(&this->images, sizeof(struct FdImage), 2)) { free(this); *texture = NULL; @@ -70,7 +69,7 @@ static bool egl_texDMABUFInit(EGL_Texture ** texture, EGLDisplay * display) EGL_Texture * parent = &this->base.base; if (!egl_texBufferStreamInit(&parent, display)) { - vector_free(this->images); + vector_destroy(&this->images); free(this); *texture = NULL; return false; @@ -86,7 +85,7 @@ static void egl_texDMABUFFree(EGL_Texture * texture) TexDMABUF * this = UPCAST(TexDMABUF , parent); egl_texDMABUFCleanup(this); - free(this->images); + vector_destroy(&this->images); egl_texBufferFree(&parent->base); free(this); @@ -113,7 +112,7 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture, EGLImage image = EGL_NO_IMAGE; struct FdImage * fdImage; - vector_forEachRef(fdImage, this->images) + vector_forEachRef(fdImage, &this->images) if (fdImage->fd == update->dmaFD) { image = fdImage->image; @@ -146,7 +145,7 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture, return false; } - if (!vector_push(this->images, &(struct FdImage) { + if (!vector_push(&this->images, &(struct FdImage) { .fd = update->dmaFD, .image = image, })) diff --git a/common/include/common/vector.h b/common/include/common/vector.h index ad736b5d..346baad7 100644 --- a/common/include/common/vector.h +++ b/common/include/common/vector.h @@ -31,9 +31,14 @@ typedef struct Vector } Vector; -Vector * vector_create(size_t itemSize, size_t capacity); +// Dynamically allocates the vector +Vector * vector_alloc(size_t itemSize, size_t capacity); void vector_free(Vector * vector); +// Uses existing vector, but dynamically allocates storage +bool vector_create(Vector * vector, size_t itemSize, size_t capacity); +void vector_destroy(Vector * vector); + inline static size_t vector_size(Vector * vector) { return vector->size; diff --git a/common/src/platform/windows/ivshmem.c b/common/src/platform/windows/ivshmem.c index fae0d015..7226cc74 100644 --- a/common/src/platform/windows/ivshmem.c +++ b/common/src/platform/windows/ivshmem.c @@ -79,13 +79,13 @@ bool ivshmemInit(struct IVSHMEM * dev) PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL; SP_DEVINFO_DATA devInfoData = {0}; SP_DEVICE_INTERFACE_DATA devInterfaceData = {0}; + Vector devices; devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_IVSHMEM, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - Vector * devices = vector_create(sizeof(struct IVSHMEMData), 1); - if (!devices) + if (!vector_create(&devices, sizeof(struct IVSHMEMData), 1)) { DEBUG_ERROR("Failed to allocate memory"); return false; @@ -93,7 +93,7 @@ bool ivshmemInit(struct IVSHMEM * dev) for (int i = 0; SetupDiEnumDeviceInfo(devInfoSet, i, &devInfoData); ++i) { - struct IVSHMEMData * device = vector_push(devices, NULL); + struct IVSHMEMData * device = vector_push(&devices, NULL); DWORD bus, addr; if (!SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_BUSNUMBER, @@ -121,10 +121,10 @@ bool ivshmemInit(struct IVSHMEM * dev) } const int shmDevice = option_get_int("os", "shmDevice"); - qsort(vector_data(devices), vector_size(devices), sizeof(struct IVSHMEMData), ivshmemComparator); + qsort(vector_data(&devices), vector_size(&devices), sizeof(struct IVSHMEMData), ivshmemComparator); struct IVSHMEMData * device; - vector_forEachRefIdx(i, device, devices) + vector_forEachRefIdx(i, device, &devices) { DWORD bus = device->busAddr >> 32; DWORD addr = device->busAddr & 0xFFFFFFFF; @@ -132,9 +132,9 @@ bool ivshmemInit(struct IVSHMEM * dev) i == shmDevice ? '*' : ' ', bus, addr >> 16, addr & 0xFFFF); } - device = vector_ptrTo(devices, shmDevice); + device = vector_ptrTo(&devices, shmDevice); memcpy(&devInfoData, &device->devInfoData, sizeof(SP_DEVINFO_DATA)); - vector_free(devices); + vector_destroy(&devices); if (SetupDiEnumDeviceInterfaces(devInfoSet, &devInfoData, &GUID_DEVINTERFACE_IVSHMEM, 0, &devInterfaceData) == FALSE) { diff --git a/common/src/vector.c b/common/src/vector.c index 969c2972..5e248299 100644 --- a/common/src/vector.c +++ b/common/src/vector.c @@ -25,22 +25,16 @@ #include #include -Vector * vector_create(size_t itemSize, size_t capacity) +Vector * vector_alloc(size_t itemSize, size_t capacity) { - Vector * vector = calloc(1, sizeof(Vector)); + Vector * vector = malloc(sizeof(Vector)); if (!vector) return NULL; - vector->itemSize = itemSize; - vector->capacity = capacity; - if (capacity) + if (!vector_create(vector, itemSize, capacity)) { - vector->data = malloc(itemSize * capacity); - if (!vector->data) - { - free(vector); - return NULL; - } + free(vector); + return NULL; } return vector; } @@ -49,10 +43,33 @@ void vector_free(Vector * vector) { if (!vector) return; - free(vector->data); + vector_destroy(vector); free(vector); } +bool vector_create(Vector * vector, size_t itemSize, size_t capacity) +{ + vector->itemSize = itemSize; + vector->capacity = capacity; + vector->size = 0; + vector->data = NULL; + + if (capacity) + { + vector->data = malloc(itemSize * capacity); + if (!vector->data) + return false; + } + return true; +} + +void vector_destroy(Vector * vector) +{ + free(vector->data); + vector->capacity = 0; + vector->itemSize = 0; +} + void * vector_push(Vector * vector, void * item) { if (vector->size >= vector->capacity)