Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TransparentBlt выдает ошибку, при выходе за границы hdcSrc 
:(
    Опции темы
GremlinProg
Дата 3.1.2009, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



обнаружил недокументированную заплатку в функции TransparentBlt
как я сейчас понимаю, она была сделана для предотвращения утечки, о которой говорится в MSDN:
Цитата(TransparentBlt)

Windows 95/98: TransparentBlt contains a memory leak that can exhaust system resources. To draw a transparent bitmap using BitBlt, see Knowledge Base article Q79212.

ошибку обнаружил при реализации потокового наложения слоев:
Код

void blt(HDC hdc,int DstX,int DstY,int DstCx,int DstCy,int SrcX,int SrcY){
    for(int i = devlist.size();i--;){
        HDC src    = devlist.at(i);
        ::TransparentBlt( hdc, DstX, DstY, DstCx, DstCy, src, SrcX, SrcY, DstCx, DstCy, clr_transparent );
    }
}

blt - метод, который накладывает разнородные слои из списка devlist в исходный hdc через ключ прозрачности clr_transparent
при этом, размеры слоев градуируются с заданным шагом, например: если минимальный размер ячейки слоя составляет 20 пикселей, то ширина и высота битмапов, выбираемых в контексты списка devlist, всегда кратны 20 пикселам
hdc не градуируется таким образом, т.е., к примеру, если в hdc выбран битмап размером 25 x 47, то в списке devlist все битмапы 20 x 40, т.е. в devlist размеры округляются в меньшую сторону

в реальной работе, если вызвать blt(hdc,0,0,25,47,0,0), то TransparentBlt на всех слоях возвращается с ошибкой "неверный параметр", соответственно, на hdc ничего не выводится

уже не знал в чем проблема, грешил на совместимость девайсов, пока не попробовал вместо TransparentBlt вызывать BitBlt, т.е. просто копирование слоев, а не наложение

предположение о несовместимости девайсов сразу отпало, поскольку BitBlt работает коректно
проверил результат работы blt с DstCx и DstCy - меньшими, либо равными размерам битмапов в devlist, т.е.
(DstCx <= 20) &&  (DstCy <= 40)
после этого и TransparentBlt заработал как надо

вобщем, код c TransparentBlt пришлось модифицировать следующим образом:
Код

void blt(HDC hdc,int DstX,int DstY,int DstCx,int DstCy,int SrcX,int SrcY){
    RECT rc;
    for(int cx,cy,i = devlist.size();i--;){
        HDC src    = devlist.at(i);
        ::GetClipBox(src,&rc);
        if(SrcX + DstCx > rc.right){
            cx    = rc.right - SrcX;
        }else{
            cx    = DstCx;
        }
        if(SrcY + DstCy > rc.bottom){
            cy    = rc.bottom - SrcY;
        }else{
            cy    = DstCy;
        }
        ::TransparentBlt( hdc, DstX, DstY, cx, cy, src, SrcX, SrcY, cx, cy, clr_transparent );
    }
}

GetClipBox дает позицию и размеры битмапа в девайсе, а DstCx и DstCy корректируются перед выводом

такое и раньше бывало, но я не пробовал использовать TransparentBlt на дискретной сетке, чтобы четко определить, в чем подвох
пишите, если будут опровержения или подтверждения по теме
чтобы не быть голословным, нужно несколько мнений, подкрепленных практикой

ссылка на документацию: http://msdn.microsoft.com/en-us/library/ms532303(VS.85).aspx

Это сообщение отредактировал(а) GremlinProg - 3.1.2009, 19:34


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 6.1.2009, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Сталкивалась с тем, что StretchBlt тоже врет при выходе за границы. Видимо, код масштабирования там кривоват... Тоже пришлось проверять и корректировать границы. Подробностей уже не помню, но не думаю, чтобы это было связано с ошибкой утечки памяти, на которую ты сослался... Не в первый раз сталкиваюсь с тем, что функции ГУИ работают по принципу "шаг вправо, шаг влево - расстрел". Ну очень недружелюбны ко всякого рода неточностям...


--------------------
...
PM   Вверх
GremlinProg
Дата 6.1.2009, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



думаешь в масштабировании дело
ну, вариант, в принципе
я просто не нашел ни одного упоминания на какие-либо ограничения по координатам в документации, поэтому и предположил

меня вообще удивляет наличие самой функции масштабирования в TransparentBlt, и отсутствие аналога BitBlt по ключу прозрачности
масштабирование в любом случае задействует больше ресурсов, чем копирование
у меня, по крайней мере, здесь масштабирование не используется, наложение битмапов производится один в один

если TransparentBlt и StretchBlt создают таки в памяти дубль битмапа, чтобы интерполировать видимые участки, то утечка так же возможна

на сколько я понимаю, TransparentBlt, по крайней мере создает маску прозрачности, что вполне логично может привести к вариантам кэширования или хэширования масок для ускорения повторного рисования (у борланда такое наблюдается, хотя там просто хэширование данных GDI-объектов), отсюда и могут вылезать проблемы с потерей каких-либо отдельных ресурсов


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 6.1.2009, 20:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Утечка действительно скорее всего связана с созданием промежуточной маски. Меня вообще удивляет упоминание TransparentBlt в контексте 95\98. Ну не было там такой функции (раньше). Она, на моей памяти, появилась в NT. Возможно, это ее симуляция как раз через промежуточную маску, которая появилась позже. MS ведь то отказывался от поддержки 98, то опять продолжал... Все эта совместимость, будь она неладна. 

А вот в NT и дальше вроде это уже через драйвер... но врать не буду, не знаю.
Насчет того, что там еще и масштабирование до кучи, так это, видимо, связано с желанием иметь универсальную функцию. 

Немного не в тему, но просто похоже. Несколько лет назад, когда NT была еще свежа, я столкнулась с удивительным багом: StrechBlt с флагом COPYSRC работала нормально, а стоило заменить COPY на любую другую операцию - OR, AND и т.д. начинались ТАКИЕ тормоза, что в первый раз я решила, что все просто зависло. Причем, это проявлялось только на некотороых видеокартах - примерно процентах на 30 (это я сужу по реакции пользователей и тестах на наших машинах). Пришлось даже ввести специальную опцию в программу -"отключить прозрачность растров" - иначе работать было просто невозможно: как сквозь смолу плыть... Самым для меня удивительным было то, что StrechBlt заполняла внеэкранный буфер, причем он точно был в моей памяти (дибсекция), а ни в какой ни в видеокарте. И при чем здесь, казалось бы, железо... Но факт оставался фактом: сочетание NT + видеокарта.

Добавлено через 1 минуту и 14 секунд
Хм, несколько лет назад... да уж как бы не все пятнадцать... smile

Добавлено через 6 минут и 36 секунд
Цитата(GremlinProg @  6.1.2009,  20:23 Найти цитируемый пост)
на сколько я понимаю, TransparentBlt, по крайней мере создает маску прозрачности, что вполне логично может привести к вариантам кэширования или хэширования масок для ускорения повторного рисования 

Ну не знаю, вряд ли - скорее они используют тернарные операции вроде MaskBlt, и это, насколько я читала, без промежуточных масок делается - на современных осях, я имею в виду.
А проблемы с выходом за границу, скорее всего - совершенно отдельный косяк: поленились отсекать (при учете масштабирования там сильно много букв получается) и оставили это дело на совести программиста.


--------------------
...
PM   Вверх
GremlinProg
Дата 6.1.2009, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Earnest @  6.1.2009,  22:12 Найти цитируемый пост)
Самым для меня удивительным было то, что StrechBlt заполняла внеэкранный буфер, причем он точно был в моей памяти (дибсекция(dibsection)), а ни в какой ни в видеокарте. И при чем здесь, казалось бы, железо... Но факт оставался фактом: сочетание NT + видеокарта.

это похоже на танцы с виртуальной памятью: виртуальный блок - локальный, а фактический - в видеопамяти
я пробовал закрепить dib в физической памяти(VirtualLock) и ничего из этого не получилось, пишет вроде как "регион уже закреплен", т.е. это точно не свопируемая память, хотя вполне может и правда закреплен самой CreateDibSection, например, если производится эмуляция )



--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 6.1.2009, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Цитата(GremlinProg @  6.1.2009,  21:37 Найти цитируемый пост)
это похоже на танцы с виртуальной памятью: виртуальный блок - локальный, а фактический - в видеопамяти

Да, я тоже пришла к такому выводу - по крайней мере, на время выполнения операции.

Знаешь, я со временем пришла к мысли, что если хочешь сделать что-то полезное, то лучше не погружаться во внутренний мир болота, а прыгать по кочкам, и черт с ним, с их химическим составом. Иначе за деревьями леса не увидишь... Иногда, конечно, приходится нырять в тину, если по другому не получается, но потом я сразу забываю подробности погружения - до следующего smile 
А может, это просто мне лень стало со временем, во всех этих багах копаться...



--------------------
...
PM   Вверх
GremlinProg
Дата 6.1.2009, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



на счет погружения - верно, но пытливый моск рукам покоя не дает
я просто считал, что баг в самой TransparentBlt, а тут - всего лишь учет границ
функция-то удобная, как раз, чтобы не погружаться в тину: SRCINVERT, SRCPAINT и т.п., опять же - маску создавать не надо
странно, что в документации об этом ни слова

Добавлено через 13 минут и 29 секунд
кстати, в тему о прозрачности:
Код

if(GetDeviceCaps(hdcDest, CAPS1) & C1_TRANSPARENT)
{
   // Special transparency background mode
      oldMode = SetBkMode(hdcDest, NEWTRANSPARENT);
      rgbBk = SetBkColor(hdcDest, rgbTransparent);
   // Actual blt is a simple source copy; transparency is automatic.
      BitBlt(hdcDest, x, y, dx, dy, hdcSrc, x0, y0, SRCCOPY);
      SetBkColor(hdcDest, rgbBk);
      SetBkMode(hdcDest, oldMode);
}

это не мое, один из источников тут, т.е. это как раз простой вариант прозрачности через BitBlt, хоть и аппаратно-зависимый, надо будет посмотреть, что быстрее и, возможно, составить триггер, если TransparentBlt таки формирует маску


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 6.1.2009, 21:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Код

#define NEWTRANSPARENT    3
#define CAPS1            94
#define C1_TRANSPARENT    1

к сожалению, мой жифорс такого не поддерживает


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 6.1.2009, 22:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Я тоже про это не слышала... интересно... наверное, это использование новых возможностей железа...
Но когда нужно поддерживать невесть какие машины, а прозрачность - далеко не главный вопрос, на первое место выходит простота кода. Его и так столько, что с ума сойти...

Кстати, интересно, есть ли баг с утечкой маски в TransparentBlt - там ведь только о Win95\98 говорится... Надо бы проверить: кажется, были непонятные утечки ресурсов, и TransparentBlt кое-где используется. Вот  выйдет народ на работу, озадачу кого-нибудь, у кого моск не такой ленивый как у меня...


--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0859 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.