Commit ebcb18d4 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

mscms: Merge the profile and transform handle tables.

parent 8a56c4db
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "mscms_priv.h" #include "mscms_priv.h"
WINE_DEFAULT_DEBUG_CHANNEL(mscms);
static CRITICAL_SECTION mscms_handle_cs; static CRITICAL_SECTION mscms_handle_cs;
static CRITICAL_SECTION_DEBUG mscms_handle_cs_debug = static CRITICAL_SECTION_DEBUG mscms_handle_cs_debug =
{ {
...@@ -40,209 +42,107 @@ static CRITICAL_SECTION_DEBUG mscms_handle_cs_debug = ...@@ -40,209 +42,107 @@ static CRITICAL_SECTION_DEBUG mscms_handle_cs_debug =
}; };
static CRITICAL_SECTION mscms_handle_cs = { &mscms_handle_cs_debug, -1, 0, 0, 0, 0 }; static CRITICAL_SECTION mscms_handle_cs = { &mscms_handle_cs_debug, -1, 0, 0, 0, 0 };
static struct profile *profiletable; static struct object **handle_table;
static cmsHTRANSFORM *transformtable; static ULONG_PTR next_handle;
static ULONG_PTR max_handles;
static unsigned int num_profile_handles;
static unsigned int num_transform_handles;
WINE_DEFAULT_DEBUG_CHANNEL(mscms);
void free_handle_tables( void )
{
free( profiletable );
profiletable = NULL;
num_profile_handles = 0;
free( transformtable );
transformtable = NULL;
num_transform_handles = 0;
DeleteCriticalSection( &mscms_handle_cs );
}
struct profile *grab_profile( HPROFILE handle )
{
DWORD_PTR index;
EnterCriticalSection( &mscms_handle_cs );
index = (DWORD_PTR)handle - 1;
if (index > num_profile_handles)
{
LeaveCriticalSection( &mscms_handle_cs );
return NULL;
}
return &profiletable[index];
}
void release_profile( struct profile *profile )
{
LeaveCriticalSection( &mscms_handle_cs );
}
cmsHTRANSFORM grab_transform( HTRANSFORM handle ) struct object *grab_object( HANDLE handle, enum object_type type )
{ {
DWORD_PTR index; struct object *obj = NULL;
ULONG_PTR index = (ULONG_PTR)handle;
EnterCriticalSection( &mscms_handle_cs ); EnterCriticalSection( &mscms_handle_cs );
if (index > 0 && index <= max_handles)
index = (DWORD_PTR)handle - 1;
if (index > num_transform_handles)
{ {
LeaveCriticalSection( &mscms_handle_cs ); index--;
return NULL; if (handle_table[index] && handle_table[index]->type == type)
{
obj = handle_table[index];
InterlockedIncrement( &obj->refs );
}
} }
return transformtable[index];
}
void release_transform( cmsHTRANSFORM transform )
{
LeaveCriticalSection( &mscms_handle_cs ); LeaveCriticalSection( &mscms_handle_cs );
}
static HPROFILE alloc_profile_handle( void )
{
DWORD_PTR index;
struct profile *p;
unsigned int count = 128;
for (index = 0; index < num_profile_handles; index++)
{
if (!profiletable[index].data) return (HPROFILE)(index + 1);
}
if (!profiletable)
{
p = calloc( count, sizeof(*p) );
}
else
{
count = num_profile_handles * 2;
p = realloc( profiletable, count * sizeof(*p) );
if (p) memset( p + num_profile_handles, 0, num_profile_handles * sizeof(*p) );
}
if (!p) return NULL;
profiletable = p;
num_profile_handles = count;
return (HPROFILE)(index + 1); TRACE( "handle %p -> %p\n", handle, obj );
return obj;
} }
HPROFILE create_profile( struct profile *profile ) void release_object( struct object *obj )
{ {
HPROFILE handle; ULONG refs = InterlockedDecrement( &obj->refs );
if (!refs)
EnterCriticalSection( &mscms_handle_cs );
if ((handle = alloc_profile_handle()))
{ {
DWORD_PTR index = (DWORD_PTR)handle - 1; if (obj->close) obj->close( obj );
profiletable[index] = *profile; TRACE( "destroying object %p\n", obj );
free( obj );
} }
LeaveCriticalSection( &mscms_handle_cs );
return handle;
} }
BOOL close_profile( HPROFILE handle ) #define HANDLE_TABLE_SIZE 4
HANDLE alloc_handle( struct object *obj )
{ {
DWORD_PTR index; struct object **ptr;
struct profile *profile; ULONG_PTR index, count;
EnterCriticalSection( &mscms_handle_cs ); EnterCriticalSection( &mscms_handle_cs );
if (!max_handles)
index = (DWORD_PTR)handle - 1;
if (index > num_profile_handles)
{ {
LeaveCriticalSection( &mscms_handle_cs ); count = HANDLE_TABLE_SIZE;
return FALSE; if (!(ptr = calloc( 1, sizeof(*ptr) * count )))
{
LeaveCriticalSection( &mscms_handle_cs );
return 0;
}
handle_table = ptr;
max_handles = count;
} }
profile = &profiletable[index]; if (max_handles == next_handle)
if (profile->file != INVALID_HANDLE_VALUE)
{ {
if (profile->access & PROFILE_READWRITE) size_t new_size, old_size = max_handles * sizeof(*ptr);
count = max_handles * 2;
new_size = count * sizeof(*ptr);
if (!(ptr = realloc( handle_table, new_size )))
{ {
DWORD written; LeaveCriticalSection( &mscms_handle_cs );
return 0;
if (SetFilePointer( profile->file, 0, NULL, FILE_BEGIN ) ||
!WriteFile( profile->file, profile->data, profile->size, &written, NULL ) ||
written != profile->size)
{
ERR( "Unable to write color profile\n" );
}
} }
CloseHandle( profile->file ); memset( (char *)ptr + old_size, 0, new_size - old_size );
handle_table = ptr;
max_handles = count;
} }
if (profile->cmsprofile) cmsCloseProfile( profile->cmsprofile ); index = next_handle;
free( profile->data ); if (handle_table[index]) ERR( "handle isn't free but should be\n" );
memset( profile, 0, sizeof(struct profile) ); handle_table[index] = obj;
InterlockedIncrement( &obj->refs );
while (next_handle < max_handles && handle_table[next_handle]) next_handle++;
LeaveCriticalSection( &mscms_handle_cs ); LeaveCriticalSection( &mscms_handle_cs );
return TRUE; TRACE( "object %p -> %Ix\n", obj, index + 1 );
} return (HANDLE)(index + 1);
static HTRANSFORM alloc_transform_handle( void )
{
DWORD_PTR index;
cmsHTRANSFORM *p;
unsigned int count = 128;
for (index = 0; index < num_transform_handles; index++)
{
if (!transformtable[index]) return (HTRANSFORM)(index + 1);
}
if (!transformtable)
{
p = calloc( count, sizeof(*p) );
}
else
{
count = num_transform_handles * 2;
p = realloc( transformtable, count * sizeof(*p) );
if (p) memset( p + num_transform_handles, 0, num_transform_handles * sizeof(*p) );
}
if (!p) return NULL;
transformtable = p;
num_transform_handles = count;
return (HTRANSFORM)(index + 1);
} }
HTRANSFORM create_transform( cmsHTRANSFORM transform ) void free_handle( HANDLE handle )
{ {
HTRANSFORM handle; struct object *obj = NULL;
ULONG_PTR index = (ULONG_PTR)handle;
EnterCriticalSection( &mscms_handle_cs ); EnterCriticalSection( &mscms_handle_cs );
if (index > 0 && index <= max_handles)
if ((handle = alloc_transform_handle()))
{ {
DWORD_PTR index = (DWORD_PTR)handle - 1; index--;
transformtable[index] = transform; if (handle_table[index])
{
obj = handle_table[index];
TRACE( "destroying handle %p for object %p\n", handle, obj );
handle_table[index] = NULL;
}
} }
LeaveCriticalSection( &mscms_handle_cs ); LeaveCriticalSection( &mscms_handle_cs );
return handle;
}
BOOL close_transform( HTRANSFORM handle ) if (obj) release_object( obj );
{
DWORD_PTR index;
cmsHTRANSFORM transform;
EnterCriticalSection( &mscms_handle_cs ); EnterCriticalSection( &mscms_handle_cs );
if (next_handle > index && !handle_table[index]) next_handle = index;
index = (DWORD_PTR)handle - 1;
if (index > num_transform_handles)
{
LeaveCriticalSection( &mscms_handle_cs );
return FALSE;
}
transform = transformtable[index];
transformtable[index] = 0;
cmsDeleteTransform( transform );
LeaveCriticalSection( &mscms_handle_cs ); LeaveCriticalSection( &mscms_handle_cs );
return TRUE;
} }
...@@ -49,7 +49,6 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, void *reserved ) ...@@ -49,7 +49,6 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, void *reserved )
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
if (reserved) break; if (reserved) break;
free_handle_tables();
break; break;
} }
return TRUE; return TRUE;
......
...@@ -27,28 +27,40 @@ ...@@ -27,28 +27,40 @@
#include <lcms2.h> #include <lcms2.h>
struct profile enum object_type
{ {
HANDLE file; OBJECT_TYPE_PROFILE,
DWORD access; OBJECT_TYPE_TRANSFORM,
char *data;
DWORD size;
cmsHPROFILE cmsprofile;
}; };
extern HPROFILE create_profile( struct profile * ) DECLSPEC_HIDDEN; struct object
extern BOOL close_profile( HPROFILE ) DECLSPEC_HIDDEN; {
enum object_type type;
LONG refs;
void (*close)( struct object * );
};
extern HTRANSFORM create_transform( cmsHTRANSFORM ) DECLSPEC_HIDDEN; struct profile
extern BOOL close_transform( HTRANSFORM ) DECLSPEC_HIDDEN; {
struct object hdr;
HANDLE file;
DWORD access;
char *data;
DWORD size;
cmsHPROFILE cmsprofile;
};
struct profile *grab_profile( HPROFILE ) DECLSPEC_HIDDEN; struct transform
cmsHTRANSFORM grab_transform( HTRANSFORM ) DECLSPEC_HIDDEN; {
struct object hdr;
cmsHTRANSFORM cmstransform;
};
void release_profile( struct profile * ) DECLSPEC_HIDDEN; extern HANDLE alloc_handle( struct object *obj ) DECLSPEC_HIDDEN;
void release_transform( cmsHTRANSFORM ) DECLSPEC_HIDDEN; extern void free_handle( HANDLE ) DECLSPEC_HIDDEN;
extern void free_handle_tables( void ) DECLSPEC_HIDDEN; struct object *grab_object( HANDLE, enum object_type ) DECLSPEC_HIDDEN;
void release_object( struct object * ) DECLSPEC_HIDDEN;
struct tag_entry struct tag_entry
{ {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
...@@ -103,6 +104,12 @@ HTRANSFORM WINAPI CreateColorTransformA( LPLOGCOLORSPACEA space, HPROFILE dest, ...@@ -103,6 +104,12 @@ HTRANSFORM WINAPI CreateColorTransformA( LPLOGCOLORSPACEA space, HPROFILE dest,
return CreateColorTransformW( &spaceW, dest, target, flags ); return CreateColorTransformW( &spaceW, dest, target, flags );
} }
static void close_transform( struct object *obj )
{
struct transform *transform = (struct transform *)obj;
if (transform->cmstransform) cmsDeleteTransform( transform->cmstransform );
}
/****************************************************************************** /******************************************************************************
* CreateColorTransformW [MSCMS.@] * CreateColorTransformW [MSCMS.@]
* *
...@@ -121,7 +128,8 @@ HTRANSFORM WINAPI CreateColorTransformA( LPLOGCOLORSPACEA space, HPROFILE dest, ...@@ -121,7 +128,8 @@ HTRANSFORM WINAPI CreateColorTransformA( LPLOGCOLORSPACEA space, HPROFILE dest,
HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, HPROFILE target, DWORD flags ) HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, HPROFILE target, DWORD flags )
{ {
HTRANSFORM ret = NULL; HTRANSFORM ret = NULL;
cmsHTRANSFORM transform; struct transform *transform;
cmsHTRANSFORM cmstransform;
struct profile *dst, *tgt = NULL; struct profile *dst, *tgt = NULL;
DWORD proofing = 0; DWORD proofing = 0;
cmsHPROFILE input; cmsHPROFILE input;
...@@ -129,11 +137,10 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, ...@@ -129,11 +137,10 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest,
TRACE( "( %p, %p, %p, %#lx )\n", space, dest, target, flags ); TRACE( "( %p, %p, %p, %#lx )\n", space, dest, target, flags );
if (!space || !(dst = grab_profile( dest ))) return FALSE; if (!space || !(dst = (struct profile *)grab_object( dest, OBJECT_TYPE_PROFILE ))) return FALSE;
if (target && !(tgt = (struct profile *)grab_object( target, OBJECT_TYPE_PROFILE )))
if (target && !(tgt = grab_profile( target )))
{ {
release_profile( dst ); release_object( &dst->hdr );
return FALSE; return FALSE;
} }
intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent; intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent;
...@@ -144,19 +151,25 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, ...@@ -144,19 +151,25 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest,
input = cmsCreate_sRGBProfile(); /* FIXME: create from supplied color space */ input = cmsCreate_sRGBProfile(); /* FIXME: create from supplied color space */
if (target) proofing = cmsFLAGS_SOFTPROOFING; if (target) proofing = cmsFLAGS_SOFTPROOFING;
transform = cmsCreateProofingTransform( input, 0, dst->cmsprofile, 0, tgt ? tgt->cmsprofile : NULL, cmstransform = cmsCreateProofingTransform( input, 0, dst->cmsprofile, 0, tgt ? tgt->cmsprofile : NULL,
intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing ); intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing );
if (!transform) if (!cmstransform)
{ {
if (tgt) release_profile( tgt ); if (tgt) release_object( &tgt->hdr );
release_profile( dst ); release_object( &dst->hdr );
return FALSE; return FALSE;
} }
ret = create_transform( transform ); if ((transform = calloc( 1, sizeof(*transform) )))
{
transform->hdr.type = OBJECT_TYPE_TRANSFORM;
transform->hdr.close = close_transform;
transform->cmstransform = cmstransform;
if (!(ret = alloc_handle( &transform->hdr ))) free( transform );
}
if (tgt) release_profile( tgt ); if (tgt) release_object( &tgt->hdr );
release_profile( dst ); release_object( &dst->hdr );
return ret; return ret;
} }
...@@ -181,7 +194,8 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil ...@@ -181,7 +194,8 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
{ {
HTRANSFORM ret = NULL; HTRANSFORM ret = NULL;
cmsHPROFILE cmsprofiles[2]; cmsHPROFILE cmsprofiles[2];
cmsHTRANSFORM transform; cmsHTRANSFORM cmstransform;
struct transform *transform;
struct profile *profile0, *profile1; struct profile *profile0, *profile1;
TRACE( "( %p, %#lx, %p, %lu, %#lx, %#lx )\n", profiles, nprofiles, intents, nintents, flags, cmm ); TRACE( "( %p, %#lx, %p, %lu, %#lx, %#lx )\n", profiles, nprofiles, intents, nintents, flags, cmm );
...@@ -194,23 +208,34 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil ...@@ -194,23 +208,34 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
return NULL; return NULL;
} }
profile0 = grab_profile( profiles[0] ); profile0 = (struct profile *)grab_object( profiles[0], OBJECT_TYPE_PROFILE );
if (!profile0) return NULL; if (!profile0) return NULL;
profile1 = grab_profile( profiles[1] ); profile1 = (struct profile *)grab_object( profiles[1], OBJECT_TYPE_PROFILE );
if (!profile1) if (!profile1)
{ {
release_profile( profile0 ); release_object( &profile0->hdr );
return NULL; return NULL;
} }
cmsprofiles[0] = profile0->cmsprofile; cmsprofiles[0] = profile0->cmsprofile;
cmsprofiles[1] = profile1->cmsprofile; cmsprofiles[1] = profile1->cmsprofile;
if (!(cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, 0, 0, *intents, 0 )))
{
release_object( &profile0->hdr );
release_object( &profile1->hdr );
return FALSE;
}
transform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, 0, 0, *intents, 0 ); if ((transform = calloc( 1, sizeof(*transform) )))
if (transform) ret = create_transform( transform ); {
transform->hdr.type = OBJECT_TYPE_TRANSFORM;
transform->hdr.close = close_transform;
transform->cmstransform = cmstransform;
if (!(ret = alloc_handle( &transform->hdr ))) free( transform );
}
release_profile( profile0 ); release_object( &profile0->hdr );
release_profile( profile1 ); release_object( &profile1->hdr );
return ret; return ret;
} }
...@@ -228,9 +253,14 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil ...@@ -228,9 +253,14 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
*/ */
BOOL WINAPI DeleteColorTransform( HTRANSFORM handle ) BOOL WINAPI DeleteColorTransform( HTRANSFORM handle )
{ {
struct transform *transform = (struct transform *)grab_object( handle, OBJECT_TYPE_TRANSFORM );
TRACE( "( %p )\n", handle ); TRACE( "( %p )\n", handle );
return close_transform( handle ); if (!transform) return FALSE;
free_handle( handle );
release_object( &transform->hdr );
return TRUE;
} }
/****************************************************************************** /******************************************************************************
...@@ -260,16 +290,16 @@ BOOL WINAPI TranslateBitmapBits( HTRANSFORM handle, PVOID srcbits, BMFORMAT inpu ...@@ -260,16 +290,16 @@ BOOL WINAPI TranslateBitmapBits( HTRANSFORM handle, PVOID srcbits, BMFORMAT inpu
DWORD outputstride, PBMCALLBACKFN callback, ULONG data ) DWORD outputstride, PBMCALLBACKFN callback, ULONG data )
{ {
BOOL ret; BOOL ret;
cmsHTRANSFORM transform = grab_transform( handle ); struct transform *transform = (struct transform *)grab_object( handle, OBJECT_TYPE_TRANSFORM );
TRACE( "( %p, %p, %#x, %lu, %lu, %lu, %p, %#x, %lu, %p, %#lx )\n", TRACE( "( %p, %p, %#x, %lu, %lu, %lu, %p, %#x, %lu, %p, %#lx )\n",
handle, srcbits, input, width, height, inputstride, destbits, output, handle, srcbits, input, width, height, inputstride, destbits, output,
outputstride, callback, data ); outputstride, callback, data );
if (!transform) return FALSE; if (!transform) return FALSE;
ret = cmsChangeBuffersFormat( transform, from_bmformat(input), from_bmformat(output) ); ret = cmsChangeBuffersFormat( transform->cmstransform, from_bmformat(input), from_bmformat(output) );
if (ret) cmsDoTransform( transform, srcbits, destbits, width * height ); if (ret) cmsDoTransform( transform->cmstransform, srcbits, destbits, width * height );
release_transform( transform ); release_object( &transform->hdr );
return ret; return ret;
} }
...@@ -295,16 +325,16 @@ BOOL WINAPI TranslateColors( HTRANSFORM handle, PCOLOR in, DWORD count, ...@@ -295,16 +325,16 @@ BOOL WINAPI TranslateColors( HTRANSFORM handle, PCOLOR in, DWORD count,
{ {
BOOL ret; BOOL ret;
unsigned int i; unsigned int i;
cmsHTRANSFORM transform = grab_transform( handle ); struct transform *transform = (struct transform *)grab_object( handle, OBJECT_TYPE_TRANSFORM );
TRACE( "( %p, %p, %lu, %d, %p, %d )\n", handle, in, count, input_type, out, output_type ); TRACE( "( %p, %p, %lu, %d, %p, %d )\n", handle, in, count, input_type, out, output_type );
if (!transform) return FALSE; if (!transform) return FALSE;
ret = cmsChangeBuffersFormat( transform, from_type(input_type), from_type(output_type) ); ret = cmsChangeBuffersFormat( transform->cmstransform, from_type(input_type), from_type(output_type) );
if (ret) if (ret)
for (i = 0; i < count; i++) cmsDoTransform( transform, &in[i], &out[i], 1 ); for (i = 0; i < count; i++) cmsDoTransform( transform->cmstransform, &in[i], &out[i], 1 );
release_transform( transform ); release_object( &transform->hdr );
return ret; return ret;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment