Конференция "WinAPI" » BitBlt
 
  • MinGW (20.04.17 20:46) [20]
    У вас DIB-секция - грубо говоря просто массив байт в памяти. Каким же образом GDI обязана "блокировать" доступ к ней? И зачем ей это?

    Это вопрос не функций GDI, а синхронизации потоков.

    Вы что, не имеете в своей многопоточной системе событий/сигналов типа "отрисовка кадра началась", "отрисовка кадра закончилась", "пора начать рисовать новый кадр"? Молотите как попало на максимуме процессора? Это как бы нехорошо.
  • dmk © (21.04.17 12:42) [21]
    >пора начать рисовать новый кадр
    Суть потоков в том, что в совокупности они настолько быстрые, что после вызова BitBlt они начинают рисовать в буфере который еще выводится. Т.е. система не успевает дорисовать до конца буфер, а потоки уже успевают в нем нарисовать новое. Флага в системе что отрисовка окончена нет. В одном потоке нет проблем.
  • D7 (24.04.17 11:32) [22]
    Вообще вроде логично что надо дождаться пока кадр выведется, и тока потом продолжать рисование на этом кадре.
    Дак может сделаете свой?

    ...
    IsDrawing:=True;
    BitBlt(...);
    IsDrawing:=False;
    ...


    Как бы логически аналог Lock/Unlock из TCanvas.
  • dmk © (24.04.17 17:23) [23]
    Вы странный человек. Это потоки. У меня рисует только один поток с ID=0.
    Остальные ждут пока он отрисует. Именно такой флаг и стоит. Только когда делается вызов BitBlt, поток ID=0 сразу после вызова функции выходит и возвращается в цикл где ждут остальные потоки, чтобы продолжить отрисовку, но сама BitBlt еще не успевает дорисовать!!! Сама функция еще не выполнена!!! Может она драйверу дает отрисовывать, может еще кому. Факт в том, что она не успевает дорисовать, а потоки уже рисуют в буфере. 20 потоков (в моем случае) это очень быстро!!!! BitBlt просто не потокобезопасна. Она жизнеспособна только в одном потоке. У меня и Synchronize стоит и флаги. Результат один и тот же.

    Еще раз привожу код:


    //Это процедура вывода на экран
    procedure TTestForm.UpdateThreads;
    var
     dp: TDrawParams;

    begin
     if (not gThreadsUpdating) then
     begin
       gThreadsUpdating := true;

       if bZBuffer then sBmp.DrawZBuffer;

       //Информация и контролы
       sBmp.DrawSmallText(Rgn.X + 10, Rgn.Y + 10, Ansistring('Рисует ID: ' + HexToStr(Word(gFirstID)) + 'h'), 1, crWhite, 255, 64);
       dp.Angle := gAngle;
       if bInfo then TestForm.DrawCenterInfo(dp);
       RepaintControls;
       DrawProgress(gProgress, false);
       UpdateWindow; // <-Здесь находитя BitBlt

       if b3D then sBmp.ClearZBuffer;

       //Очищаем фон
       ClearBack;

       //Счетчик обновлений
       Inc(gNumBufferUpdates);

       gThreadsUpdating := false;
     end;
    end;

    //Это цикл отрисовки
    procedure QThread.Execute;
    var
     cP: TFloatPoint;
     Params: TDrawParams;

    label
     StopDraw;

    begin
     //Параметры по умолчанию
     Params := FillParams;

     //Центр вращения
     cP.fX := cX;
     cP.fY := cY;

     //Порядковый номер потока
     NumberID := GetFreeID(ThreadID);

     //Заполняем параметры
     Params.cX := cX;
     Params.cY := cY;
     Params.ThreadID := NumberID;
     Params.Angle := gAngle;

     //Отсечение всего региона
     if bClip then
       Params.R := lmR else
       Params.R := Rgn;

     //Цикл отрисовки
     while (gDrawCounter <= gNumDrawCycles) do
     begin
       //Превышение индекса объектов
       //учитывается в программе отрисовки
       //Рисуем ...
       gDrawProc(Params);

       //Обновляет буфер самый шустрый поток
       if (ThreadID = gFirstID) then
       begin
         //Обновляем буфер
         Synchronize(TestForm.UpdateThreads); //<-- Synchronize не обязательно, но может моргать!
         //TestForm.UpdateThreads;
         //Прогресс
         gProgress := Round(gDrawCounter / (gNumDrawCycles - 1) * 100);
         //Кол-во циклов отрисовки
         Inc(gDrawCounter);
         //Следующий угол
         gAngle := RorAngle(gAngle, gAngleInc);
         //Сброс кол-ва отрисованных объектов
         gObjectIndex := 0;
       end;//if (gNumEntered)

       //Устанавливаем флаг завершения отрисовки
       FPaints[NumberID] := True;

       //Остальные потоки ждут здесь
       //пока первый поток не отрисует буфер
       //или все потоки не соберутся здесь
       while (not PaintsFinished) do
       begin
         //Проверка на превышение циклов отрисовки
         if (gDrawCounter >= gNumDrawCycles) then goto StopDraw;
       end;

       //Проверка на ESC
       if gESC then goto StopDraw;
     end;//while

    StopDraw:

     //Устанавливаем флаг завершения отрисовки
     FPaints[NumberID] := True;

     //Ждем здесь пока остальные потоки не закончат отрисовку
     while (not PaintsFinished) do
     begin
     end;
    end;

  • dmk © (24.04.17 17:40) [24]
    Короче добавил CriticalSection в UpdateThreads - скорость снизилась, но глюки исчезли.
    Значит Игорь Шевченко ©   (09.02.17 21:39) [4] был прав.
 
Конференция "WinAPI" » BitBlt
Есть новые Нет новых   [118639   +35][b:0][p:0]