render: Report pixmap usage of pictures to resource extension.
Signed-off-by: Erkki Seppälä <erkki.seppala@vincit.fi> Signed-off-by: Rami Ylimäki <rami.ylimaki@vincit.fi> Reviewed-by: Mikhail Gusarov <dottedmag@dottedmag.net> Reviewed-by: Tiago Vignatti <tiago.vignatti@nokia.com>
This commit is contained in:
parent
96864bfa95
commit
e83388cc70
27
Xext/xres.c
27
Xext/xres.c
|
@ -27,6 +27,7 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "picturestr.h"
|
||||||
|
|
||||||
/** @brief Holds fragments of responses for ConstructClientIds.
|
/** @brief Holds fragments of responses for ConstructClientIds.
|
||||||
*
|
*
|
||||||
|
@ -288,6 +289,17 @@ ResGetApproxPixmapBytes(PixmapPtr pix)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
ResFindResourcePixmaps(pointer value, XID id, RESTYPE type, pointer cdata)
|
||||||
|
{
|
||||||
|
SizeType sizeFunc = GetResourceTypeSizeFunc(type);
|
||||||
|
ResourceSizeRec size = { 0, 0 };
|
||||||
|
unsigned long *bytes = cdata;
|
||||||
|
|
||||||
|
sizeFunc(value, id, &size);
|
||||||
|
*bytes += size.pixmapRefSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
ResFindPixmaps(pointer value, XID id, pointer cdata)
|
ResFindPixmaps(pointer value, XID id, pointer cdata)
|
||||||
{
|
{
|
||||||
unsigned long *bytes = (unsigned long *) cdata;
|
unsigned long *bytes = (unsigned long *) cdata;
|
||||||
|
@ -322,6 +334,14 @@ ResFindGCPixmaps(pointer value, XID id, pointer cdata)
|
||||||
*bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
|
*bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ResFindPicturePixmaps(pointer value, XID id, pointer cdata)
|
||||||
|
{
|
||||||
|
#ifdef RENDER
|
||||||
|
ResFindResourcePixmaps(value, id, PictureType, cdata);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ProcXResQueryClientPixmapBytes(ClientPtr client)
|
ProcXResQueryClientPixmapBytes(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -356,6 +376,13 @@ ProcXResQueryClientPixmapBytes(ClientPtr client)
|
||||||
FindClientResourcesByType(clients[clientID], RT_GC,
|
FindClientResourcesByType(clients[clientID], RT_GC,
|
||||||
ResFindGCPixmaps, (pointer) (&bytes));
|
ResFindGCPixmaps, (pointer) (&bytes));
|
||||||
|
|
||||||
|
#ifdef RENDER
|
||||||
|
/* Render extension picture pixmaps. */
|
||||||
|
FindClientResourcesByType(clients[clientID], PictureType,
|
||||||
|
ResFindPicturePixmaps,
|
||||||
|
(pointer)(&bytes));
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef COMPOSITE
|
#ifdef COMPOSITE
|
||||||
/* FIXME: include composite pixmaps too */
|
/* FIXME: include composite pixmaps too */
|
||||||
#endif
|
#endif
|
||||||
|
|
197
dix/resource.c
197
dix/resource.c
|
@ -141,6 +141,7 @@ Equipment Corporation.
|
||||||
#include "xace.h"
|
#include "xace.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
|
#include "gcstruct.h"
|
||||||
|
|
||||||
#ifdef XSERVER_DTRACE
|
#ifdef XSERVER_DTRACE
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -182,50 +183,212 @@ RESTYPE TypeMask;
|
||||||
|
|
||||||
struct ResourceType {
|
struct ResourceType {
|
||||||
DeleteType deleteFunc;
|
DeleteType deleteFunc;
|
||||||
|
SizeType sizeFunc;
|
||||||
int errorValue;
|
int errorValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by all resources that don't specify a function to calculate
|
||||||
|
* resource size. Currently this is used for all resources with
|
||||||
|
* insignificant memory usage.
|
||||||
|
*
|
||||||
|
* @see GetResourceTypeSizeFunc, SetResourceTypeSizeFunc
|
||||||
|
*
|
||||||
|
* @param[in] value Pointer to resource object.
|
||||||
|
*
|
||||||
|
* @param[in] id Resource ID for the object.
|
||||||
|
*
|
||||||
|
* @param[out] size Fill all fields to zero to indicate that size of
|
||||||
|
* resource can't be determined.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
GetDefaultBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
|
{
|
||||||
|
size->resourceSize = 0;
|
||||||
|
size->pixmapRefSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate drawable size in bytes. Reference counting is not taken
|
||||||
|
* into account.
|
||||||
|
*
|
||||||
|
* @param[in] drawable Pointer to a drawable.
|
||||||
|
*
|
||||||
|
* @return Estimate of total memory usage for the drawable.
|
||||||
|
*/
|
||||||
|
static unsigned long
|
||||||
|
GetDrawableBytes(DrawablePtr drawable)
|
||||||
|
{
|
||||||
|
int bytes = 0;
|
||||||
|
|
||||||
|
if (drawable)
|
||||||
|
{
|
||||||
|
int bytesPerPixel = drawable->bitsPerPixel >> 3;
|
||||||
|
int numberOfPixels = drawable->width * drawable->height;
|
||||||
|
bytes = numberOfPixels * bytesPerPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate pixmap size in bytes. Reference counting is taken into
|
||||||
|
* account. Any extra data attached by extensions and drivers is not
|
||||||
|
* taken into account. The purpose of this function is to estimate
|
||||||
|
* memory usage that can be attributed to single reference of the
|
||||||
|
* pixmap.
|
||||||
|
*
|
||||||
|
* @param[in] value Pointer to a pixmap.
|
||||||
|
*
|
||||||
|
* @param[in] id Resource ID of pixmap. If the pixmap hasn't been
|
||||||
|
* added as resource, just pass value->drawable.id.
|
||||||
|
*
|
||||||
|
* @param[out] size Estimate of memory usage attributed to a single
|
||||||
|
* pixmap reference.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
GetPixmapBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
|
{
|
||||||
|
PixmapPtr pixmap = value;
|
||||||
|
|
||||||
|
size->resourceSize = 0;
|
||||||
|
size->pixmapRefSize = 0;
|
||||||
|
|
||||||
|
if (pixmap && pixmap->refcnt)
|
||||||
|
{
|
||||||
|
DrawablePtr drawable = &pixmap->drawable;
|
||||||
|
size->resourceSize = GetDrawableBytes(drawable);
|
||||||
|
size->pixmapRefSize = size->resourceSize / pixmap->refcnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate window size in bytes. The purpose of this function is to
|
||||||
|
* estimate memory usage that can be attributed to all pixmap
|
||||||
|
* references of the window.
|
||||||
|
*
|
||||||
|
* @param[in] value Pointer to a window.
|
||||||
|
*
|
||||||
|
* @param[in] id Resource ID of window.
|
||||||
|
*
|
||||||
|
* @param[out] size Estimate of memory usage attributed to a all
|
||||||
|
* pixmap references of a window.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
GetWindowBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
|
{
|
||||||
|
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
||||||
|
ResourceSizeRec pixmapSize = { 0, 0 };
|
||||||
|
WindowPtr window = value;
|
||||||
|
|
||||||
|
/* Currently only pixmap bytes are reported to clients. */
|
||||||
|
size->resourceSize = 0;
|
||||||
|
|
||||||
|
/* Calculate pixmap reference sizes. */
|
||||||
|
size->pixmapRefSize = 0;
|
||||||
|
if (window->backgroundState == BackgroundPixmap)
|
||||||
|
{
|
||||||
|
PixmapPtr pixmap = window->background.pixmap;
|
||||||
|
pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
|
||||||
|
size->pixmapRefSize += pixmapSize.pixmapRefSize;
|
||||||
|
}
|
||||||
|
if (window->border.pixmap && !window->borderIsPixel)
|
||||||
|
{
|
||||||
|
PixmapPtr pixmap = window->border.pixmap;
|
||||||
|
pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
|
||||||
|
size->pixmapRefSize += pixmapSize.pixmapRefSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate graphics context size in bytes. The purpose of this
|
||||||
|
* function is to estimate memory usage that can be attributed to all
|
||||||
|
* pixmap references of the graphics context.
|
||||||
|
*
|
||||||
|
* @param[in] value Pointer to a graphics context.
|
||||||
|
*
|
||||||
|
* @param[in] id Resource ID of graphics context.
|
||||||
|
*
|
||||||
|
* @param[out] size Estimate of memory usage attributed to a all
|
||||||
|
* pixmap references of a graphics context.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
GetGcBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
|
{
|
||||||
|
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
||||||
|
ResourceSizeRec pixmapSize = { 0, 0 };
|
||||||
|
GCPtr gc = value;
|
||||||
|
|
||||||
|
/* Currently only pixmap bytes are reported to clients. */
|
||||||
|
size->resourceSize = 0;
|
||||||
|
|
||||||
|
/* Calculate pixmap reference sizes. */
|
||||||
|
size->pixmapRefSize = 0;
|
||||||
|
if (gc->stipple)
|
||||||
|
{
|
||||||
|
PixmapPtr pixmap = gc->stipple;
|
||||||
|
pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
|
||||||
|
size->pixmapRefSize += pixmapSize.pixmapRefSize;
|
||||||
|
}
|
||||||
|
if (gc->tile.pixmap && !gc->tileIsPixel)
|
||||||
|
{
|
||||||
|
PixmapPtr pixmap = gc->tile.pixmap;
|
||||||
|
pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
|
||||||
|
size->pixmapRefSize += pixmapSize.pixmapRefSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct ResourceType *resourceTypes;
|
static struct ResourceType *resourceTypes;
|
||||||
|
|
||||||
static const struct ResourceType predefTypes[] = {
|
static const struct ResourceType predefTypes[] = {
|
||||||
[RT_NONE & (RC_LASTPREDEF - 1)] = {
|
[RT_NONE & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = (DeleteType) NoopDDA,
|
.deleteFunc = (DeleteType) NoopDDA,
|
||||||
|
.sizeFunc = GetDefaultBytes,
|
||||||
.errorValue = BadValue,
|
.errorValue = BadValue,
|
||||||
},
|
},
|
||||||
[RT_WINDOW & (RC_LASTPREDEF - 1)] = {
|
[RT_WINDOW & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = DeleteWindow,
|
.deleteFunc = DeleteWindow,
|
||||||
|
.sizeFunc = GetWindowBytes,
|
||||||
.errorValue = BadWindow,
|
.errorValue = BadWindow,
|
||||||
},
|
},
|
||||||
[RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
|
[RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = dixDestroyPixmap,
|
.deleteFunc = dixDestroyPixmap,
|
||||||
|
.sizeFunc = GetPixmapBytes,
|
||||||
.errorValue = BadPixmap,
|
.errorValue = BadPixmap,
|
||||||
},
|
},
|
||||||
[RT_GC & (RC_LASTPREDEF - 1)] = {
|
[RT_GC & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = FreeGC,
|
.deleteFunc = FreeGC,
|
||||||
|
.sizeFunc = GetGcBytes,
|
||||||
.errorValue = BadGC,
|
.errorValue = BadGC,
|
||||||
},
|
},
|
||||||
[RT_FONT & (RC_LASTPREDEF - 1)] = {
|
[RT_FONT & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = CloseFont,
|
.deleteFunc = CloseFont,
|
||||||
|
.sizeFunc = GetDefaultBytes,
|
||||||
.errorValue = BadFont,
|
.errorValue = BadFont,
|
||||||
},
|
},
|
||||||
[RT_CURSOR & (RC_LASTPREDEF - 1)] = {
|
[RT_CURSOR & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = FreeCursor,
|
.deleteFunc = FreeCursor,
|
||||||
|
.sizeFunc = GetDefaultBytes,
|
||||||
.errorValue = BadCursor,
|
.errorValue = BadCursor,
|
||||||
},
|
},
|
||||||
[RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
|
[RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = FreeColormap,
|
.deleteFunc = FreeColormap,
|
||||||
|
.sizeFunc = GetDefaultBytes,
|
||||||
.errorValue = BadColor,
|
.errorValue = BadColor,
|
||||||
},
|
},
|
||||||
[RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
|
[RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = FreeClientPixels,
|
.deleteFunc = FreeClientPixels,
|
||||||
|
.sizeFunc = GetDefaultBytes,
|
||||||
.errorValue = BadColor,
|
.errorValue = BadColor,
|
||||||
},
|
},
|
||||||
[RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
|
[RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = OtherClientGone,
|
.deleteFunc = OtherClientGone,
|
||||||
|
.sizeFunc = GetDefaultBytes,
|
||||||
.errorValue = BadValue,
|
.errorValue = BadValue,
|
||||||
},
|
},
|
||||||
[RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
|
[RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = DeletePassiveGrab,
|
.deleteFunc = DeletePassiveGrab,
|
||||||
|
.sizeFunc = GetDefaultBytes,
|
||||||
.errorValue = BadValue,
|
.errorValue = BadValue,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -256,6 +419,7 @@ CreateNewResourceType(DeleteType deleteFunc, const char *name)
|
||||||
lastResourceType = next;
|
lastResourceType = next;
|
||||||
resourceTypes = types;
|
resourceTypes = types;
|
||||||
resourceTypes[next].deleteFunc = deleteFunc;
|
resourceTypes[next].deleteFunc = deleteFunc;
|
||||||
|
resourceTypes[next].sizeFunc = GetDefaultBytes;
|
||||||
resourceTypes[next].errorValue = BadValue;
|
resourceTypes[next].errorValue = BadValue;
|
||||||
|
|
||||||
/* Called even if name is NULL, to remove any previous entry */
|
/* Called even if name is NULL, to remove any previous entry */
|
||||||
|
@ -264,6 +428,39 @@ CreateNewResourceType(DeleteType deleteFunc, const char *name)
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the function used to calculate resource size. Extensions and
|
||||||
|
* drivers need to be able to determine the current size calculation
|
||||||
|
* function if they want to wrap or override it.
|
||||||
|
*
|
||||||
|
* @param[in] type Resource type used in size calculations.
|
||||||
|
*
|
||||||
|
* @return Function to calculate the size of a single
|
||||||
|
* resource.
|
||||||
|
*/
|
||||||
|
SizeType
|
||||||
|
GetResourceTypeSizeFunc(RESTYPE type)
|
||||||
|
{
|
||||||
|
return resourceTypes[type & TypeMask].sizeFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the default function that calculates resource size. For
|
||||||
|
* example, video driver knows better how to calculate pixmap memory
|
||||||
|
* usage and can therefore wrap or override size calculation for
|
||||||
|
* RT_PIXMAP.
|
||||||
|
*
|
||||||
|
* @param[in] type Resource type used in size calculations.
|
||||||
|
*
|
||||||
|
* @param[in] sizeFunc Function to calculate the size of a single
|
||||||
|
* resource.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
SetResourceTypeSizeFunc(RESTYPE type, SizeType sizeFunc)
|
||||||
|
{
|
||||||
|
resourceTypes[type & TypeMask].sizeFunc = sizeFunc;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetResourceTypeErrorValue(RESTYPE type, int errorValue)
|
SetResourceTypeErrorValue(RESTYPE type, int errorValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -152,12 +152,37 @@ typedef Bool (*FindComplexResType) (pointer /*value */ ,
|
||||||
XID /*id */ ,
|
XID /*id */ ,
|
||||||
pointer /*cdata */ );
|
pointer /*cdata */ );
|
||||||
|
|
||||||
|
/* Structure for estimating resource memory usage. Memory usage
|
||||||
|
* consists of space allocated for the resource itself and of
|
||||||
|
* references to other resources. Currently the most important use for
|
||||||
|
* this structure is to estimate pixmap usage of different resources
|
||||||
|
* more accurately. */
|
||||||
|
typedef struct {
|
||||||
|
/* Size of resource itself. Zero if not implemented. */
|
||||||
|
unsigned long resourceSize;
|
||||||
|
/* Size attributed to pixmap references from the resource. */
|
||||||
|
unsigned long pixmapRefSize;
|
||||||
|
} ResourceSizeRec, *ResourceSizePtr;
|
||||||
|
|
||||||
|
typedef void (*SizeType)(pointer /*value*/,
|
||||||
|
XID /*id*/,
|
||||||
|
ResourceSizePtr /*size*/);
|
||||||
|
|
||||||
extern _X_EXPORT RESTYPE CreateNewResourceType(DeleteType /*deleteFunc */ ,
|
extern _X_EXPORT RESTYPE CreateNewResourceType(DeleteType /*deleteFunc */ ,
|
||||||
const char * /*name */ );
|
const char * /*name */ );
|
||||||
|
|
||||||
extern _X_EXPORT void SetResourceTypeErrorValue(RESTYPE /*type */ ,
|
extern _X_EXPORT void SetResourceTypeErrorValue(RESTYPE /*type */ ,
|
||||||
int /*errorValue */ );
|
int /*errorValue */ );
|
||||||
|
|
||||||
|
extern _X_EXPORT SizeType GetResourceTypeSizeFunc(
|
||||||
|
RESTYPE /*type*/);
|
||||||
|
|
||||||
|
extern _X_EXPORT void SetResourceTypeSizeFunc(
|
||||||
|
RESTYPE /*type*/, SizeType /*sizeFunc*/);
|
||||||
|
|
||||||
|
extern _X_EXPORT void SetResourceTypeErrorValue(
|
||||||
|
RESTYPE /*type*/, int /*errorValue*/);
|
||||||
|
|
||||||
extern _X_EXPORT RESTYPE CreateNewResourceClass(void);
|
extern _X_EXPORT RESTYPE CreateNewResourceClass(void);
|
||||||
|
|
||||||
extern _X_EXPORT Bool InitClientResources(ClientPtr /*client */ );
|
extern _X_EXPORT Bool InitClientResources(ClientPtr /*client */ );
|
||||||
|
|
|
@ -591,6 +591,27 @@ PictureParseCmapPolicy(const char *name)
|
||||||
return PictureCmapPolicyInvalid;
|
return PictureCmapPolicyInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @see GetDefaultBytes */
|
||||||
|
static void
|
||||||
|
GetPictureBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
|
{
|
||||||
|
PicturePtr picture = value;
|
||||||
|
|
||||||
|
/* Currently only pixmap bytes are reported to clients. */
|
||||||
|
size->resourceSize = 0;
|
||||||
|
|
||||||
|
/* Calculate pixmap reference sizes. */
|
||||||
|
size->pixmapRefSize = 0;
|
||||||
|
if (picture->pDrawable && (picture->pDrawable->type == DRAWABLE_PIXMAP))
|
||||||
|
{
|
||||||
|
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
||||||
|
ResourceSizeRec pixmapSize = { 0, 0 };
|
||||||
|
PixmapPtr pixmap = (PixmapPtr)picture->pDrawable;
|
||||||
|
pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
|
||||||
|
size->pixmapRefSize += pixmapSize.pixmapRefSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bool
|
Bool
|
||||||
PictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
|
PictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
|
||||||
{
|
{
|
||||||
|
@ -602,6 +623,7 @@ PictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
|
||||||
PictureType = CreateNewResourceType(FreePicture, "PICTURE");
|
PictureType = CreateNewResourceType(FreePicture, "PICTURE");
|
||||||
if (!PictureType)
|
if (!PictureType)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
SetResourceTypeSizeFunc(PictureType, GetPictureBytes);
|
||||||
PictFormatType = CreateNewResourceType(FreePictFormat, "PICTFORMAT");
|
PictFormatType = CreateNewResourceType(FreePictFormat, "PICTFORMAT");
|
||||||
if (!PictFormatType)
|
if (!PictFormatType)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
Loading…
Reference in New Issue