mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 22:01:46 +00:00
[host] dxgi: add helper to manage COM object memory
This commit is contained in:
parent
c100df4037
commit
69b984aa2c
3 changed files with 234 additions and 0 deletions
|
@ -7,6 +7,7 @@ add_library(capture_DXGI STATIC
|
||||||
src/d3d12.c
|
src/d3d12.c
|
||||||
src/ods_capture.c
|
src/ods_capture.c
|
||||||
src/util.c
|
src/util.c
|
||||||
|
src/com_ref.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions("-DCOBJMACROS -DINITGUID")
|
add_definitions("-DCOBJMACROS -DINITGUID")
|
||||||
|
|
137
host/platform/Windows/capture/DXGI/src/com_ref.c
Normal file
137
host/platform/Windows/capture/DXGI/src/com_ref.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2023 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define COMREF_INTERNAL
|
||||||
|
#include "com_ref.h"
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
#include "common/vector.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int scope;
|
||||||
|
IUnknown * value;
|
||||||
|
IUnknown *** ref;
|
||||||
|
}
|
||||||
|
COMRef;
|
||||||
|
|
||||||
|
static int comScope = -1;
|
||||||
|
static Vector comObjectsLocal = {0};
|
||||||
|
static Vector comObjectsGlobal = {0};
|
||||||
|
|
||||||
|
bool comRef_init(unsigned globals, unsigned locals)
|
||||||
|
{
|
||||||
|
if (!vector_create(&comObjectsGlobal, sizeof(COMRef), globals))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!vector_create(&comObjectsLocal, sizeof(COMRef), locals))
|
||||||
|
{
|
||||||
|
vector_destroy(&comObjectsGlobal);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void comRef_free(void)
|
||||||
|
{
|
||||||
|
COMRef * ref;
|
||||||
|
|
||||||
|
if (comScope > -1)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("There is %d unmatched `comRef_scopePush` calls", comScope+1);
|
||||||
|
vector_forEachRef(ref, &comObjectsLocal)
|
||||||
|
if (ref->value)
|
||||||
|
IUnknown_Release(ref->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector_forEachRef(ref, &comObjectsGlobal)
|
||||||
|
{
|
||||||
|
if (ref->ref)
|
||||||
|
*ref->ref = NULL;
|
||||||
|
|
||||||
|
if (ref->value)
|
||||||
|
IUnknown_Release(ref->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
comScope = -1;
|
||||||
|
vector_destroy(&comObjectsLocal);
|
||||||
|
vector_destroy(&comObjectsGlobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IUnknown ** comRef_new(Vector * vector, IUnknown *** dst)
|
||||||
|
{
|
||||||
|
// we must not allow the vector to grow as if the realloc moves to a new
|
||||||
|
// address it will invalidate any external pointers to members in it
|
||||||
|
DEBUG_ASSERT(vector_size(vector) < vector_capacity(vector) &&
|
||||||
|
"comRef vector too small!");
|
||||||
|
|
||||||
|
COMRef * ref = (COMRef *)vector_push(vector, NULL);
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to allocate ram for com object");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref->scope = comScope;
|
||||||
|
ref->ref = dst;
|
||||||
|
ref->value = NULL;
|
||||||
|
|
||||||
|
if (dst)
|
||||||
|
*dst = &ref->value;
|
||||||
|
|
||||||
|
return &ref->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
IUnknown ** comRef_newGlobal(IUnknown *** dst)
|
||||||
|
{
|
||||||
|
return comRef_new(&comObjectsGlobal, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
IUnknown ** comRef_newLocal(IUnknown *** dst)
|
||||||
|
{
|
||||||
|
IUnknown ** ret = comRef_new(&comObjectsLocal, NULL);
|
||||||
|
*dst = ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void comRef_scopePush(void) { ++comScope; }
|
||||||
|
|
||||||
|
void comRef_scopePop(void)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(comScope >= 0);
|
||||||
|
|
||||||
|
COMRef * ref;
|
||||||
|
while(vector_size(&comObjectsLocal) > 0)
|
||||||
|
{
|
||||||
|
ref = (COMRef *)vector_ptrTo(&comObjectsLocal,
|
||||||
|
vector_size(&comObjectsLocal) - 1);
|
||||||
|
|
||||||
|
if (ref->scope < comScope)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ref->value)
|
||||||
|
IUnknown_Release(ref->value);
|
||||||
|
|
||||||
|
vector_pop(&comObjectsLocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
--comScope;
|
||||||
|
}
|
96
host/platform/Windows/capture/DXGI/src/com_ref.h
Normal file
96
host/platform/Windows/capture/DXGI/src/com_ref.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2023 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These functions are to assist in tracking and relasing COM objects
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the com object tracking
|
||||||
|
*/
|
||||||
|
bool comRef_init(unsigned globals, unsigned locals);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release globals and deinitialize the com object tracking
|
||||||
|
*/
|
||||||
|
void comRef_free(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new global COM reference
|
||||||
|
*/
|
||||||
|
IUnknown ** comRef_newGlobal(IUnknown *** dst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new locally scoped COM reference
|
||||||
|
*/
|
||||||
|
IUnknown ** comRef_newLocal(IUnknown *** dst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define and create a new locally scoped COM reference
|
||||||
|
*/
|
||||||
|
#define comRef_defineLocal(type, name) \
|
||||||
|
type ** name; \
|
||||||
|
comRef_newLocal(&name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release a COM reference immediately
|
||||||
|
* This is just a helper, the ref is still tracked if used again
|
||||||
|
*/
|
||||||
|
inline static ULONG comRef_release(IUnknown ** ref)
|
||||||
|
{
|
||||||
|
ULONG count = 0;
|
||||||
|
if (*ref)
|
||||||
|
count = IUnknown_Release(*ref);
|
||||||
|
*ref = NULL;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new local scope
|
||||||
|
*/
|
||||||
|
void comRef_scopePush(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exit from a local scope and release all locals
|
||||||
|
*/
|
||||||
|
void comRef_scopePop (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Macros to prevent needing to typecast calls to these methods
|
||||||
|
*/
|
||||||
|
#ifndef COMREF_INTERNAL
|
||||||
|
#define comRef_newGlobal(dst) comRef_newGlobal((IUnknown ***)(dst))
|
||||||
|
#define comRef_newLocal(dst) comRef_newLocal((IUnknown ***)(dst))
|
||||||
|
#define comRef_release(ref) comRef_release((IUnknown **)(ref))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a local to a global
|
||||||
|
*/
|
||||||
|
#define comRef_toGlobal(dst, src) \
|
||||||
|
{ \
|
||||||
|
IUnknown ** global = comRef_newGlobal(&(dst)); \
|
||||||
|
DEBUG_ASSERT(global && "comRef_newGlobal failed\n"); \
|
||||||
|
*global = (IUnknown*)*(src); \
|
||||||
|
*(src) = NULL; \
|
||||||
|
}
|
Loading…
Reference in a new issue