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.