WINE/Разработчику/Изображения
Проблемы с изображением
Ситуация с DIB
Есть DC. Он связан с устройством, и его обрабатывают функции драйвера (WINEX11).
Созданный на его основе CompatibleDC (memdc), выполняющий все операции над DIB (в памяти), должен обрабатываться функциями DIB Engine.
В gdi32 вызов нужной функции драйвера происходит на основе таблицы с функциями, указатель на которую (dc->funcs) хранится в объекте. Если функция присутствует, она вызывается. Если функции нет, возможно использование альтернативной реализации прямо из gdi32.
Последняя реализация использует хак в SelectObject, которая если вызвана для memdc, подгружает драйвер DIB, его функции попадают в таблицу, и далее для этого объекта вызываются только функции DIB Engine.
Наша цель в этой таблице функций (для memdc) постепенно (по мере разработки) подменять функции драйвера на функции DIB Engine.
CyrilMargorin /11.10.2008 11:48/
Есть ли для этого Test cases? Сегодня к вечеру попробую просмотреть, чтобы понять выше написаное (без кода, описание не совсем понятно).
Кирилл, я уже и потерял связь давно... Может быть спишемся, или в аське/джаббере? JID: lav@im.etersoft.ru
CyrilMargorin /11.10.2008 17:56/
К сожалению, из дома в аське стараюсь не сидеть (ибо она у меня рабочая). Джаббер соответсвует е-мылу: comargo@gmail.com, но тоже забываю включить дома. На работе включена всегда.
Сейчас пока включил.
Некие проблемы с графикой
Проблемы с изображением можно увидеть на
- Русский фотограф - можно списаться с автором
- Заставке к КОМПАС - падает при запуске без патча
- Также на этом падает Консультант+ (если запускать с патчем ;))
Ситуация:
1. код около функции BITMAP_Object неверный
2. патч тоже неверный
3. в /wine/dlls/gdi/tests/bitmap.c
должны быть тесты об этом, они тоже неверные (если их исправить, они должны работать на Windows и не работать в wine)
Патч, корректирующий проблему для КОМПАСА
Index: bitmap.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/bitmap.c,v
retrieving revision 1.7
diff -u -u -r1.7 bitmap.c
--- bitmap.c 13 Apr 2005 16:11:18 -0000 1.7
+++ dlls/gdi/bitmap.c 17 May 2005 18:44:52 -0000
@@ -612,6 +612,7 @@
/***********************************************************************
* BITMAP_GetObject
+ * Fill buffer with BITMAP or DIPSECTION (depends on dib field and count size)
*/
static INT BITMAP_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
{
@@ -621,26 +622,19 @@
{
if( !buffer )
return sizeof(DIBSECTION);
- if (count < sizeof(DIBSECTION))
- {
- if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
- }
- else
- {
- if (count > sizeof(DIBSECTION)) count = sizeof(DIBSECTION);
- }
-
- memcpy( buffer, bmp->dib, count );
- return count;
- }
- else
- {
- if( !buffer )
- return sizeof(BITMAP);
- if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
- memcpy( buffer, &bmp->bitmap, count );
- return count;
+ if (count >= sizeof(DIBSECTION))
+ {
+ count = sizeof(DIBSECTION);
+ memcpy( buffer, bmp->dib, count );
+ return count;
+ }
+ if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
}
+ if( !buffer )
+ return sizeof(BITMAP);
+ if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
+ memcpy( buffer, &bmp->bitmap, count );
+ return count;
}
//Похоже надо через таблицу цветов превращать из 24х битовой в 4х битовую....
При этом надо учитывать, что кроме 24х битового дисплея бывает еще и 32 и 16.... а иногда и 8ми.....
В теории можно повнимательней просмотреть код около функции X11_GetDIBits() (или как то так она называется) и еще (скорее всего) необходимо сделать схожие изменения в функции X11_SetBitmapBits...//
CyrilMargorin /10.12.2005 01:38/
Появилась для обсуждение идея, перевести функцию CopyImage с Get/SetBitmapBits на Get/SetDIBits. Попытка сделать это в общем-то была успешна....
Index: dlls/user/cursoricon.c
===================================================================
RCS file: /home/wine/wine/dlls/user/cursoricon.c,v
retrieving revision 1.22
diff -u -r1.22 cursoricon.c
--- dlls/user/cursoricon.c 5 Dec 2005 20:07:34 -0000 1.22
+++ dlls/user/cursoricon.c 9 Dec 2005 22:29:21 -0000
@@ -2322,14 +2322,39 @@
if (!GetObjectW( hnd, sizeof(bm), &bm )) return 0;
bm.bmBits = NULL;
- if ((res = CreateBitmapIndirect(&bm)))
- {
- char *buf = HeapAlloc( GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight );
- GetBitmapBits( hnd, bm.bmWidthBytes * bm.bmHeight, buf );
- SetBitmapBits( res, bm.bmWidthBytes * bm.bmHeight, buf );
- HeapFree( GetProcessHeap(), 0, buf );
- }
- return (HICON)res;
+ if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL );
+ if (screen_dc)
+ {
+ if((res = CreateCompatibleBitmap(screen_dc,bm.bmWidth,bm.bmHeight)))
+ {
+ BITMAPINFO* pbmi;
+ char *buf;
+ char *bmibuf;
+ int nColor=0;
+ if(bm.bmBitsPixel <= 8)
+ nColor = 1<<bm.bmBitsPixel;
+ if(bm.bmBitsPixel == 15 || bm.bmBitsPixel == 16)
+ nColor = 3;
+ bmibuf = HeapAlloc( GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER)+nColor*sizeof(RGBQUAD));
+ pbmi = (BITMAPINFO*)bmibuf;
+ ZeroMemory(pbmi,sizeof(BITMAPINFOHEADER)+nColor*sizeof(RGBQUAD));
+ pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
+ pbmi->bmiHeader.biWidth = bm.bmWidth;
+ pbmi->bmiHeader.biHeight = bm.bmHeight;
+ pbmi->bmiHeader.biPlanes = bm.bmPlanes;
+ pbmi->bmiHeader.biBitCount = bm.bmBitsPixel;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ buf = HeapAlloc( GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight );
+ GetDIBits(screen_dc,hnd,0,bm.bmHeight,buf,pbmi,DIB_RGB_COLORS);
+ SetDIBits(screen_dc,res,0,bm.bmHeight,buf,pbmi,DIB_RGB_COLORS);
+ HeapFree( GetProcessHeap(), 0, bmibuf );
+ HeapFree( GetProcessHeap(), 0, buf );
+ }
+ return (HICON)res;
+ }
+ /* In case of error it should return 0
+ */
+ return 0;
}
case IMAGE_ICON:
return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
CyrilMargorin /13.02.2006 23:32/
После дальнейшего исследования проблемы с пропавшей заставкой в
Компасе выяснилось, что проблема состоит в том, что функция GetDIBits
возвращает "черную" картинку.
При этом, компиляция wine с выключенной поддержкой Shared Memory
картинку проявило.
Таким образом наткнулись на следующий момент
Есть следующий код:
dlls/x11drv/dib.c функция X11DRV_DIB_GetImageBits
XImage *bmpImage;
wine_tsx11_lock();
if (descr->image)
bmpImage = descr->image;
else {
bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
descr->infoWidth, lines, 32, 0 );
bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
if(bmpImage->data == NULL) {
ERR("Out of memory!\n");
XDestroyImage( bmpImage );
wine_tsx11_unlock();
return lines;
}
}
#ifdef HAVE_LIBXXSHM
if (descr->image && descr->useShm)
{
int saveRed, saveGreen, saveBlue;
TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
gdi_display, descr->drawable, bmpImage,
descr->xSrc, descr->ySrc, AllPlanes);
saveRed = bmpImage->red_mask;
saveBlue= bmpImage->blue_mask;
saveGreen = bmpImage->green_mask;
XShmGetImage( gdi_display, descr->drawable, bmpImage,
descr->xSrc, descr->ySrc, AllPlanes);
bmpImage->red_mask = saveRed;
bmpImage->blue_mask = saveBlue;
bmpImage->green_mask = saveGreen;
}
else
#endif /* HAVE_LIBXXSHM */
{
TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
descr->width, lines, AllPlanes, ZPixmap,
bmpImage, descr->xDest, descr->yDest );
}
В случае, если descr->image равен нулю, создается новый XImage, без поддержки Shared Memory, но если был передан параметр useShm, для получения XImage из Pixmap используется функция с поддержкой Shared Memory, которая есстественно не срабатывает в данном случае. (Схожий код исспользуется в X11DRV_DIB_SetImageBits).
Таким образом, первый патч заключается в проверке, создавалася ли XImage локально, или исспользовался внешний?
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/dib.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -p -r1.49 -r1.50
--- wine/dlls/x11drv/dib.c 2006/02/13 13:09:31 1.49
+++ wine/dlls/x11drv/dib.c 2006/02/13 13:09:49 1.50
@@ -3626,7 +3626,7 @@ static int X11DRV_DIB_SetImageBits( cons
descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
descr->width, descr->height);
#ifdef HAVE_LIBXXSHM
- if (descr->useShm)
+ if (descr->image && descr->useShm)
{
XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
@@ -3670,7 +3670,7 @@ static int X11DRV_DIB_GetImageBits( cons
}
#ifdef HAVE_LIBXXSHM
- if (descr->useShm)
+ if (descr->image && descr->useShm)
{
int saveRed, saveGreen, saveBlue;
Второй момент:
В функции X11DRV_GetDIBits при заполнении структуры X11DRV_DIB_IMAGEBITS_DESCR descr в поле image записывался NULL. Соответственно было изменено на существующий XImage из physBitmap.
RCS file: /home/wine/wine/dlls/x11drv/dib.c,v retrieving revision 1.48 retrieving revision 1.49 diff -u -p -r1.48 -r1.49 --- wine/dlls/x11drv/dib.c 2005/12/13 18:25:52 1.48 +++ wine/dlls/x11drv/dib.c 2006/02/13 13:09:31 1.49 @@ -4080,7 +4080,7 @@ INT X11DRV_GetDIBits( X11DRV_PDEVICE *ph descr.physDev = physDev; descr.palentry = palette; descr.bits = bits; - descr.image = NULL; + descr.image = physBitmap->image; descr.infoWidth = width; descr.lines = lines; descr.depth = physBitmap->pixmap_depth;
Оба патча вошли в репозиторий cvs.winehq.org 13 февраля 2006.