Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2009.04.26;
Скачать: [xml.tar.bz2];

Вниз

Спрашивали тут ;)   Найти похожие ветки 

 
homm ©   (2007-10-21 15:05) [0]

Функция AlphaDraw. Принимаемый параметры — 2 32-х битных битмапа, на первый из них рисуется на второй, по альфа маске, которая содержится в резервных битах второго изображения. Изображение копируется на смещение X и Y, которые не должны быть отрицательны.

procedure AlphaDraw(DestBitmap, SourceBitmap: TBitmap; X, Y: Integer);
type
  ARGBQuad = array [0..0] of TRGBQuad;
  PARGBQuad = ^ARGBQuad;
  AByte = array [0..0] of Byte;
  PAByte = ^AByte;
var
  SL1, SL2: PARGBQuad;
  V1, V2: TRGBQuad;
  R: ^TRGBQuad;
  i, j: Integer;
  A_1, A: Integer;
  Delta1, Delta2: DWORD;
  W, H: Integer;
begin
  if (X >= DestBitmap.Width) or (Y >= DestBitmap.Height) then
    exit;
  W := min(SourceBitmap.Width, DestBitmap.Width-X);
  H := min(SourceBitmap.Height, DestBitmap.Height-Y);
  SL1 := DestBitmap.ScanLine[Y];
  SL2 := SourceBitmap.ScanLine[0];
  Delta1 := DWORD(DestBitmap.ScanLine[1]) - DWORD(DestBitmap.ScanLine[0]);
  Delta2 := DWORD(SourceBitmap.ScanLine[1]) - DWORD(SourceBitmap.ScanLine[0]);
  if CPUisMMX then begin
    asm
      pushad

      pxor mm0, mm0
      mov eax, $01010101
      movd mm5, eax
      punpcklbw mm5, mm0
      movq mm6, mm5
      psllw mm5, 8

      mov ecx, H
      push ecx
@@loop1:
        mov esi, [SL2]
        mov edi, [SL1]
        mov eax, [X]
        lea edi, [edi+ eax*4]
        mov ecx, W
@@loop2:

          movd mm1, [esi]
          punpcklbw mm1, mm0
          movd mm2, [edi]
          punpcklbw mm2, mm0

          mov al, [esi + 3]
          mov ah, al
          mov bx, ax
          shl eax, 16
          mov ax, bx

          movd mm4, eax
          punpcklbw mm4, mm0
          paddw mm4, mm6
          movq mm3, mm5
          psubw mm3, mm4

          pmullw mm1, mm3
          pmullw mm2, mm4

          paddw mm1, mm2

          psrlw mm1, 8

          packuswb mm1, mm0
          movd [edi], mm1

          add esi, 4
          add edi, 4
        dec ecx
        jnz @@loop2

        mov eax, [Delta1]
        add [SL1], eax
        mov eax, [Delta2]
        add [SL2], eax
      dec [esp]
      jnz @@loop1

      pop ecx
      emms
      popad
    end;
  end else begin
    for i := 0 to H-1 do begin
      for j := 0 to W-1 do begin
        V1 := SL1[j+X];
        V2 := SL2[j];
        A := V2.rgbReserved+1;
        A_1 := 256-V2.rgbReserved;
        R := @SL1[j+X];
        R.rgbBlue := (V2.rgbBlue*A_1+V1.rgbBlue*A) shr 8;
        R.rgbGreen := (V2.rgbGreen*A_1+V1.rgbGreen*A) shr 8;
        R.rgbRed := (V2.rgbRed*A_1+V1.rgbRed*A) shr 8;
      end;
      SL1 := Pointer(DWORD(SL1) + Delta1);
      SL2 := Pointer(DWORD(SL2) + Delta2);
    end;
  end;
end;


 
homm ©   (2007-10-21 15:05) [1]

> на первый из них рисуется на второй

на первый из них рисуется второй


 
homm ©   (2007-10-21 15:07) [2]

Ах, да, самое главное забыл :)
MMX версия работатет в 2,7 раз быстрее паскалевской.


 
homm ©   (2007-10-21 15:54) [3]

Вариант №2
производительность MMX версии +2%
производительность Pascal версии +11%
Добавлена совместимость с компилятором пятой дельфи.

procedure AlphaDraw(DestBitmap, SourceBitmap: TBitmap; X, Y: Integer);
type
  ARGBQuad = array [0..0] of TRGBQuad;
  PARGBQuad = ^ARGBQuad;
  AByte = array [0..0] of Byte;
  PAByte = ^AByte;
var
  SL1, SL2: PARGBQuad;
  V1, V2: TRGBQuad;
  R: ^TRGBQuad;
  i, j: Integer;
  A_1, A: Integer;
  Delta1, Delta2: DWORD;
  W, H: Integer;
begin
  if (X >= DestBitmap.Width) or (Y >= DestBitmap.Height) then
    exit;
  W := min(SourceBitmap.Width, DestBitmap.Width-X);
  H := min(SourceBitmap.Height, DestBitmap.Height-Y);
  SL1 := Pointer(DWORD(DestBitmap.ScanLine[Y])+X*4);
  SL2 := SourceBitmap.ScanLine[0];
  Delta1 := DWORD(DestBitmap.ScanLine[1]) - DWORD(DestBitmap.ScanLine[0]);
  Delta2 := DWORD(SourceBitmap.ScanLine[1]) - DWORD(SourceBitmap.ScanLine[0]);
  if CPUisMMX then begin
    asm
      pushad

      //pxor mm0, mm0
      db $0F, $EF, $C0
      mov eax, $01010101
      //movd mm5, eax
      db $0F, $6E, $E8
      //punpcklbw mm5, mm0
      db $0F, $60, $E8
      //movq mm6, mm5
      db $0F, $6F, $F5
      //psllw mm5, 8
      db $0F, $71, $F5, $08

      mov ecx, H
      push ecx
@@loop1:
        mov esi, [SL2]
        mov edi, [SL1]
        mov ecx, W
@@loop2:

          //movd mm1, [esi]
          db $0F, $6E, $0E
          //punpcklbw mm1, mm0
          db $0F, $60, $C8
          //movd mm2, [edi]
          db $0F, $6E, $17
          //punpcklbw mm2, mm0
          db $0F, $60, $D0

          mov ah, [esi + 3]
          mov al, ah
          shl eax, 8
          mov al, ah

          //movd mm4, eax
          db $0F, $6E, $E0
          //punpcklbw mm4, mm0
          db $0F, $60, $E0
          //paddw mm4, mm6
          db $0F, $FD, $E6
          //movq mm3, mm5
          db $0F, $6F, $DD
          //psubw mm3, mm4
          db $0F, $F9, $DC

          //pmullw mm1, mm3
          db $0F, $D5, $CB
          //pmullw mm2, mm4
          db $0F, $D5, $D4

          //paddw mm1, mm2
          db $0F, $FD, $CA

          //psrlw mm1, 8
          db $0F, $71, $D1, $08

          //packuswb mm1, mm0
          db $0F, $67, $C8
          //movd [edi], mm1
          db $0F, $7E, $0F

          add esi, 4
          add edi, 4
        dec ecx
        jnz @@loop2

        mov eax, [Delta1]
        add [SL1], eax
        mov eax, [Delta2]
        add [SL2], eax
      dec dword ptr [esp]
      jnz @@loop1

      pop ecx
      //emms
      db $0F, $77
      popad
    end;
  end else begin
    for i := 0 to H-1 do begin
      for j := 0 to W-1 do begin
        V1 := SL1[j];
        V2 := SL2[j];
        A := V2.rgbReserved+1;
        A_1 := 256-V2.rgbReserved;
        R := @SL1[j];
        R.rgbBlue := (V2.rgbBlue*A_1+V1.rgbBlue*A) shr 8;
        R.rgbGreen := (V2.rgbGreen*A_1+V1.rgbGreen*A) shr 8;
        R.rgbRed := (V2.rgbRed*A_1+V1.rgbRed*A) shr 8;
      end;
      SL1 := Pointer(DWORD(SL1) + Delta1);
      SL2 := Pointer(DWORD(SL2) + Delta2);
    end;
  end;
end;


 
homm ©   (2007-10-21 17:30) [4]

Черт, зачем писал %)

Глянул Graphics32.

Их асемблерный вариант без ММХ работает даже быстрее моего ММХ-а. А уж их ММХ и подавно %)

Моя в печале.


 
antonn ©   (2007-10-21 20:22) [5]

я уже нашел, для моего велосипедного класса:
procedure Bliting_alpha_MMX(BTSourc,BTDest:TBT; x,y:integer);
var SrcBits: DWORD;
     DstBits: DWORD;
     xTo, sx, YTo, ddx, ddy, sy, w, h, dstw, dsth: integer;
     inc1, inc2: integer;
begin
if BTSourc.CPUisMMX then begin
     SrcBits := DWORD(BTSourc.P);
     DstBits := DWORD(BTDest.p);
 w:= BTSourc.DIBWidth;
 h:= BTSourc.DIBHeight;
 dstw:= BTDest.DIBWidth;
 dsth:= BTDest.DIBHeight;
 XTo:= x+W-1;
 YTo:= y+H-1;
 if (y>=dstH) or (x>=dstW) or (YTo<0) or (XTo<0) then exit;
 asm
   xor  eax, eax
   mov  ddx, eax
   mov  ddy, eax
 end;
 sx:= W;
 sy:= H;

 if X<0 then
   begin
     ddx:= -X;
     inc( sx, X);
     x:= 0;
   end;

 if Y<0 then
   begin
     ddy:= -Y;
     inc( sy, Y);
     y:= 0;
   end;

 if XTo>=dstw then
   dec( sx, XTo-dstw+1);

 if YTo>=dsth then
   dec( sy, YTo-dsth+1);

 if (sx<=0) or (sy<=0) then exit;

     SrcBits := DWORD(@BTSourc.P^[ (ddy*BTSourc.DIBWidth)+ddx ]);
     DstBits := DWORD(@BTDest.P^[(y*BTDest.DIBWidth)+x ]);
     inc1:=BTDest.DIBWidth*SizeOf(BTElement);
     inc2:=BTSourc.DIBWidth*SizeOf(BTElement);
     asm
   push      edi
   push      esi

   pxor      mm7, mm7  

   mov       edx, $10101

   push      $000000FF  
   push      $00FF00FF
   movq      mm5, [esp]  

 @outer_loop:
   mov       esi, SrcBits
   mov       edi, DstBits
   mov       ecx, sx

 @inner_loop:
   mov       eax, [esi]
   movd      mm0, [esi]
   test      eax, $FF000000
   jz        @noblend
   shr       eax, 24
   add       esi, 4
   imul      eax, edx    
   punpcklbw mm0, mm7

   movd      mm6, eax
   movd      mm1, [edi]
   punpcklbw mm6, mm7
   punpcklbw mm1, mm7
   pmullw    mm0, mm6    
   pxor      mm6, mm5  
   pmullw    mm1, mm6  

   paddw     mm0, mm1  
   psrlw     mm0, 8    
   add       edi, 4

   packuswb  mm0, mm7    
   movd      [edi-4], mm0
   dec       ecx
   jnz       @inner_loop
   jmp       @endline

 @noblend:
   add       edi, 4
   add       esi, 4
   dec       ecx
   jnz       @inner_loop

 @endline:
   mov       ecx, inc1
   mov       eax, inc2
   add       DstBits, ecx
   add       SrcBits, eax
   dec       sy
   jnz       @outer_loop

   add       esp, 8
   emms
   pop       esi
   pop       edi
 end;
end;
end;


 
homm ©   (2007-10-21 20:30) [6]

> [5] antonn ©   (21.10.07 20:22)
> if BTSourc.CPUisMMX then begin

А если нет, что будешь делать ;) ?


 
antonn ©   (2007-10-21 20:38) [7]

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


 
homm ©   (2007-10-21 20:53) [8]

> [7] antonn ©   (21.10.07 20:38)
> а еще в ней плохо то, что она обнуляет альфу конечного изображения
> в местах блитинга первого :(

Моя тоже обновляет. Хочешь версию, которая не обновляет? Счас попробуя состряпать.


 
antonn ©   (2007-10-21 20:58) [9]

не, я бы предпочел ту, которая берет наиболее яркую - если фон боле яркий - берем фон, если у накладываемого более яркая - берем ее (яркая - где более непрозрачная получается). В версии без ММХ все пучком, но хочется в ММХ :)
procedure Bliting_alpha(BTSourc,BTDest:TBT; x,y:integer);
var SrcBits: DWORD; DstBits: DWORD;
   xTo, sx, YTo, ddx, ddy, sy, w, h, dstw, dsth: integer;
   inc1, inc2: integer;
begin
 w:= BTSourc.DIBWidth;
 h:= BTSourc.DIBHeight;
 dstw:= BTDest.DIBWidth;
 dsth:= BTDest.DIBHeight;
 XTo:= x+W-1;
 YTo:= y+H-1;
 if (y>=dstH) or (x>=dstW) or (YTo<0) or (XTo<0) then exit;
 asm
   xor  eax, eax
   mov  ddx, eax
   mov  ddy, eax
 end;
 sx:= W;
 sy:= H;

 if X<0 then
   begin
     ddx:= -X;
     inc( sx, X);
     x:= 0;
   end;

 if Y<0 then
   begin
     ddy:= -Y;
     inc( sy, Y);
     y:= 0;
   end;

 if XTo>=dstw then
   dec( sx, XTo-dstw+1);

 if YTo>=dsth then
   dec( sy, YTo-dsth+1);

 if (sx<=0) or (sy<=0) then exit;

     SrcBits := DWORD(@BTSourc.P^[ (ddy*BTSourc.DIBWidth)+ddx ]);
     DstBits := DWORD(@BTDest.P^[(y*BTDest.DIBWidth)+x ]);
     inc1:=BTDest.DIBWidth*SizeOf(BTElement);
     inc2:=BTSourc.DIBWidth*SizeOf(BTElement);

 asm
   push  ebx
   push  edi
   push  esi

 @outer_loop:
   mov   ecx, sx
   mov   edi, DstBits
   mov   esi, SrcBits
 @loop:
   mov   bl, byte ptr [esi+3]
   mov   bh, byte ptr [esi+3]
   and   bl, bl
   je    @skiptransparent

   mov   al, [esi]
   not   bh

   mul   al, bl
   mov   dl, ah
   mov   al, [edi]
   mul   al, bh
   add   dl, ah
   mov   [edi], dl

   mov   al, [esi+1]
   mul   al, bl
   mov   dl, ah
   mov   al, [edi+1]
   mul   al, bh
   add   dl, ah
   mov   [edi+1], dl

   mov   al, [esi+2]
   mul   al, bl
   mov   dl, ah
   mov   al, [edi+2]
   mul   al, bh
   add   dl, ah
   mov   [edi+2], dl

 @skiptransparent:
   add   esi, 4
   add   edi, 4
   dec   ecx
   jnz   @loop

 @l1:
   mov   ecx, inc1
   mov   eax, inc2
   add   DstBits, ecx
   add   SrcBits, eax
   dec   sy
   jnz   @outer_loop

   pop   esi
   pop   edi
   pop   ebx
 end;
end;


 
antonn ©   (2007-10-21 21:11) [10]

кстати, а сейчас вообще есть процессоры без поддержки ММХ, но наботающие под управлением вин2к минимум? :)


 
homm ©   (2007-10-21 21:16) [11]

antonn, а ты зачем сам решил велоспортом занятся? :)

Чем Graphics32 не устроил?


 
homm ©   (2007-10-21 21:18) [12]

> [9] antonn ©   (21.10.07 20:58)
> не, я бы предпочел ту, которая берет наиболее яркую - если
> фон боле яркий - берем фон, если у накладываемого более
> яркая - берем ее (яркая - где более непрозрачная получается)
> . В версии без ММХ все пучком, но хочется в ММХ :)

С ММХ такое — врятли. Там всего 57 команд, вся суть в конвеерной обработке данных, без ветвлений.

Выкладывать версию, которая не портит фоновую прозрачность?


 
DVM ©   (2007-10-21 21:19) [13]

без MMX уже найти сложно. PentiumPRO может еще где.


 
antonn ©   (2007-10-21 21:22) [14]


> antonn, а ты зачем сам решил велоспортом занятся? :)

мне нужна функция, которая обработает массив (в котором битмап, вообще это небольшая унификация некоторых вещей, но да ладно), а в График32 куча всего и не нужные мне махинации с битмапами (в смысле разные битности и все такое), короче я за велосипедный спорт! :)


> Выкладывать версию, которая не портит фоновую прозрачность?

давай, для коррекции:)
(обожаю ассемблерные процедурки, прям гоню на них:))


 
homm ©   (2007-10-21 21:27) [15]

> [14] antonn ©   (21.10.07 21:22)
> а в График32 куча всего и не нужные мне махинации с битмапами
> (в смысле разные битности и все такое)

Да нет, как я посмотрел, там вокруг TBitmap32 все крутится.


> давай, для коррекции:)

procedure GenAlphaTable;
var
  I: Integer;
  P: ^Longword;
begin
  GetMem(AlphaTable, 256*16);
  P := AlphaTable;
  for I := 1 to 256 do begin
    P^ := I + I shl 16;
    Inc(P);
    P^ := I;
    //PWORD(P)^ := $0;
    Inc(P);
  end;
  for I := 256 downto 1 do begin
    P^ := I + I shl 16;
    Inc(P);
    P^ := I + $1000000;
    Inc(P);
  end;
end;



procedure AlphaDraw(DestBitmap, SourceBitmap: TBitmap; X, Y: Integer);
type
  ARGBQuad = array [0..0] of TRGBQuad;
  PARGBQuad = ^ARGBQuad;
  AByte = array [0..0] of Byte;
  PAByte = ^AByte;
var
  SL1, SL2: PARGBQuad;
  V1, V2: TRGBQuad;
  R: ^TRGBQuad;
  i, j: Integer;
  A_1, A: Integer;
  Delta1, Delta2: DWORD;
  W, H: Integer;
begin
  if AlphaTable = nil then
    GenAlphaTable;
  if (X >= DestBitmap.Width) or (Y >= DestBitmap.Height) then
    exit;
  W := min(SourceBitmap.Width, DestBitmap.Width-X);
  H := min(SourceBitmap.Height, DestBitmap.Height-Y);
  SL1 := Pointer(Integer(DestBitmap.ScanLine[Y])+X*4);
  SL2 := SourceBitmap.ScanLine[0];
  Delta1 := DWORD(DestBitmap.ScanLine[1]) - DWORD(DestBitmap.ScanLine[0]);
  Delta2 := DWORD(SourceBitmap.ScanLine[1]) - DWORD(SourceBitmap.ScanLine[0]);
  if CPUisMMX then begin
    asm
      pushad

      //pxor mm0, mm0
      db $0F, $EF, $C0
      mov eax, $01010101
      //movd mm5, eax
      db $0F, $6E, $E8
      //punpcklbw mm5, mm0
      db $0F, $60, $E8
      //movq mm6, mm5
      db $0F, $6F, $F5
      //psllw mm5, 8
      db $0F, $71, $F5, $08

      xor edx, edx
      mov ecx, H
      push ecx
@@loop1:
        mov esi, [SL2]
        mov edi, [SL1]
        mov ecx, W
@@loop2:

          //movd mm1, [esi]
          db $0F, $6E, $0E
          //punpcklbw mm1, mm0
          db $0F, $60, $C8
          //movd mm2, [edi]
          db $0F, $6E, $17
          //punpcklbw mm2, mm0
          db $0F, $60, $D0

          mov dl, [esi+3]
          mov ebx, [AlphaTable]
          lea ebx, [ebx+edx*8]
          movq mm3, [ebx]
          add ebx, 256*8
          movq mm4, [ebx]

          //pmullw mm1, mm3
          db $0F, $D5, $CB
          //pmullw mm2, mm4
          db $0F, $D5, $D4

          //paddw mm1, mm2
          db $0F, $FD, $CA

          //psrlw mm1, 8
          db $0F, $71, $D1, $08

          //packuswb mm1, mm0
          db $0F, $67, $C8
          //movd [edi], mm1
          db $0F, $7E, $0F

          add esi, 4
          add edi, 4
        dec ecx
        jnz @@loop2

        mov eax, [Delta1]
        add [SL1], eax
        mov eax, [Delta2]
        add [SL2], eax
      dec dword ptr [esp]
      jnz @@loop1

      pop ecx
      //emms
      db $0F, $77
      popad
    end;
  end else begin
    for i := 0 to H-1 do begin
      for j := 0 to W-1 do begin
        V1 := SL1[j];
        V2 := SL2[j];
        A_1 := V2.rgbReserved+1;
        if A_1 = 1 then
        else if A_1 = $100 then begin
          SL1[j] := SL2[j];
        end else begin
          A := 256-V2.rgbReserved;
          R := @SL1[j];
          R.rgbBlue := (V2.rgbBlue*A_1+V1.rgbBlue*A) shr 8;
          R.rgbGreen := (V2.rgbGreen*A_1+V1.rgbGreen*A) shr 8;
          R.rgbRed := (V2.rgbRed*A_1+V1.rgbRed*A) shr 8;
        end;
      end;
      SL1 := Pointer(DWORD(SL1) + Delta1);
      SL2 := Pointer(DWORD(SL2) + Delta2);
    end;
  end;
end;


По хорошему еше в конце обработки нужно где-то пристроить  FreeMem(AlphaTable);

ЗЫ Идея с GenAlphaTable полностью слизана с Graphics32, реализация осмыслена и переработана.


 
antonn ©   (2007-10-21 22:25) [16]


> ЗЫ Идея с GenAlphaTable полностью слизана с Graphics32,
> реализация осмыслена и переработана.

вот из-за этой альфаТайбл я и не стал разбираться с Г32 :)


 
Sapersky   (2007-10-22 14:33) [17]

вся суть в конвеерной обработке данных, без ветвлений.

Некую имитацию ветвлений можно делать с помощью pcmpeq/pcmpgt и масок, которые они дают; в качестве примера см. вывод с прозрачным цветом (MMXTransPut) из SpriteUtils. Хотя расписывание сколь-нибудь сложного алгоритма с ветвлениями на MMX - это, конечно, кошмар.

Хорошее описание MMX (со схемами - я только по ним и понял, как работает, например, упаковка/распаковка):
http://www.tommesani.com/

А от ассемблера без MMX толку немного. Если хотя бы примерно представлять, как работает оптимизатор и периодически заглядывать в CPU window, можно и на Паскале писать не (ну или не намного) хуже. Система команд ведь та же самая.
По особенностям компилятора есть такой документ:
http://dennishomepage.gugs-cats.dk/CodingForSpeedInDelphi.doc
Не идеальный, но кое-что почерпнуть можно.


 
antonn ©   (2007-10-24 17:31) [18]

чего то я не пойму, как сделать так, чтобы в первом байте была наиболее яркая альфа, из той же SpriteUtils.
   push      edi
   push      esi

   pxor      mm7, mm7    

   mov       edx, $10101

   push      $001100FF   // маска первого двойного (11 это альфа, по идее там FF:))
   push      $00FF00FF   // маска второго двойного
   movq      mm5, [esp]  // mm5 - $0011.00FF|00FF.00FF
@outer_loop:
   mov       esi, SrcBits
   mov       edi, DstBits
   mov       ecx, sx

 @inner_loop:
   mov       eax, [esi]
   movd      mm0, [esi]
   test      eax, $FF000000
   jz        @noblend //там просто копирование и цикл дальше
   shr       eax, 24
   add       esi, 4
   imul      eax, edx    // размножить байт прозрачности
   punpcklbw mm0, mm7

   movd      mm6, eax
   movd      mm1, [edi]
   punpcklbw mm6, mm7
   punpcklbw mm1, mm7
   pmullw    mm0, mm6    // получить произведение источника в mm0
   pxor      mm6, mm5    // получить обратную прозрачность в mm6
   pmullw    mm1, mm6    // получить произведение источника в mm0
 
   paddw     mm0, mm1    // сложить

   psrlw     mm0, 8      // переместить в младшую сторону для упаковки

   add       edi, 4

   packuswb  mm0, mm7    // упаковать перед записью на место

//в mm0 конечные 4 байта


 
homm ©   (2007-10-24 17:41) [19]

> [18] antonn ©   (24.10.07 17:31)
> чего то я не пойму, как сделать так, чтобы в первом байте
> была наиболее яркая альфа

С помошью ММХ — никак. В крайнем сучае считать альфу до, запоминать, считать пиксель, писать альфу.


 
antonn ©   (2007-10-24 17:54) [20]

воблин :(
а в [15] тогда как сделать максимальную в конечном пикселе? а то там сейчас остается от фона.


 
Sapersky   (2007-10-24 18:19) [21]

ИМХО можно, хотя не факт, что будет достаточно быстро работать (хоть и MMX, но слишком много операций на пиксель получается, причём значительное кол-во операций ради одной альфы - принцип SIMD нарушается).

The PCMPGT (Packed Compare for Greater Than) instructions compare the signed data elements in the destination operand to the signed data elements in the source operand. If the signed data elements in the destination register are greater than those in the source operand, the corresponding data element in the destination operand is set to all ones, otherwise it is set to all zeros. PCMPGT supports packed byte (PCMPGTB), packed word (PCMPGTW) and packed doubleword (PCMPGTD) data types.

Потом примерно так же, как и в MMXTransPut - одну альфу and с полученной маской, другую andn, и всё вместе or.

Выражаясь псевдокодом:
A1 > A2:
A1 PCMPGT A2 = $FF
(A1 and $FF) or (A2 and (not $FF)) = A1

A1 < A2:
A1 PCMPGT A2 = $00
дальше сам :)


 
homm ©   (2007-10-24 18:37) [22]

> [21] Sapersky   (24.10.07 18:19)
> Потом примерно так же, как и в MMXTransPut - одну альфу
> and с полученной маской, другую andn, и всё вместе or.

и получется почти как «В крайнем сучае считать альфу до, запоминать, считать пиксель, писать альфу.»


 
Sapersky   (2007-10-24 19:09) [23]

Ну пусть это будет Твоя Гениальная Идея, мне не жалко :)
Я писал о том, что это можно делать через MMX.

Кстати, ещё следует учитывать: The PCMPGT instructions compare the signed data elements.


 
homm ©   (2007-10-24 19:43) [24]

> [23] Sapersky   (24.10.07 19:09)
> Ну пусть это будет Твоя Гениальная Идея, мне не жалко :)

Я не об авторстве, а о том, что в обоих случаях считаем альфу отдельно, прибавляем к результирующему пикселу.


 
antonn ©   (2007-10-25 23:03) [25]

итак, опять я тут %)
в общем, сделал функцию, которая берет для конечного изображения максимальную альфу из исходного и конечного. Сама функция в [9], после обработки третьего байта (как раз перед @skiptransparent:) вставить это:
   mov   al, [edi+3]
   cmp bl,al
   jb @set_al
   mov [edi+3],bl

очень буду рад, если кто нибудь предложит более быстрый вариант (я вот подумал, а нет ли такой команды, которая из источника и приемника берет максимальное и кладет в приемник? тогда этот кусок кода можно до двух строк сократить, а то мне cmp и ждамп как то не нравится:))
но суть не в этом коде, он уже в 7 раз быстрее сканлайна, хочется с ММХ :)
В [18] есть часть кода, сразу после написаного следует
movd      [edi-4], mm0
т.е. в принципе можно запихнуть mm0 в eax, и работать дальше "не с ммх".
Так вот, подскажите, как быть, в EAX значение байта, где альфа берется фоновая. Теперь нужно сравнить альфу источника и фона, и в [eax+3] записать максимальную альфу. Я уже припух, не могу сообразить:)
movd      eax, mm0
..
mov   bl, byte ptr [edi+3]
mov   dl, byte ptr [esi+3]
cmp bl,dl
jb @set_al
//так вот, как в байт eax поместить bl? (или dl, запутался уже)
//mov [edi+3],bl - ессно так нельзя :)
//да и вообще мне кажется, что bl и dl зря взял, испортят они дело:)
@set_al:
..
movd      [edi-4], eax


 
antonn ©   (2007-10-25 23:36) [26]

сильно не смяться:)
пишу как в коде [18], просто в конце еще лезу в память, можно как нибудь ускорить?
   mov      [edi-4], eax

   mov       bl, byte ptr [edi-4+3]
   mov       al, byte ptr [esi+3]
   cmp       al,bl
   jb @set_al
   mov      [edi-4+3], al
   @set_al:


 
Sapersky   (2007-10-26 12:52) [27]

а нет ли такой команды, которая из источника и приемника берет максимальное и кладет в приемник

Точно, есть - PMAXUB. Забыл я про неё, видимо, из-за того, что это enhanced MMX, а не обычный.
http://www.tommesani.com/SSEPrimer.html

Если без MMX, то CMOV. Правда, она избавляет только от jump, cmp или test всё равно нужны.

Что касается "как сделать то и это на обычном asm" - напиши на Паскале и см. CPU window.


 
antonn ©   (2007-10-26 20:43) [28]

а как быстро записать в 4й байт в eax? т.е. для памяти я делаю [esi+3] и пишу 4й байт, а как тоже самое сделать для регистра?


 
homm ©   (2007-10-26 21:30) [29]

> [28] antonn ©   (26.10.07 20:43)
> а как быстро записать в 4й байт в eax? т.е. для памяти я
> делаю [esi+3] и пишу 4й байт, а как тоже самое сделать для
> регистра?


rol eax, 8
mov al, XXX
ror eax, 8


 
antonn ©   (2007-10-26 22:32) [30]

Спасибо!
сделал этот альфаканал, но с ММХ чуть медленней, чем без него получилось :)
   movd      eax, mm0

   rol eax, 8
   mov      bl, byte ptr [esi+3]
   cmp  bl,al
   jb @set_al
   mov al, bl
   @set_al:
   ror eax, 8

   mov      [edi-4], eax


 
homm ©   (2007-10-26 22:48) [31]

> [30] antonn ©   (26.10.07 22:32)

обрати внимание не команду PREFETCHT0.

Расскажи, заодно, чем пользуешся при написании, потому что я действую почти вслепую… В мануалах, которые ест ьу меня нет такой команды, например как pshufw. В идеале хотелось бы подробный справочник с примерами по всем mmx sse и 3dnow до кучи. Если еше и ч86 будет, вообше замечательно.


 
homm ©   (2007-10-26 22:50) [32]

Ах, да интел.ком не предлагать, хочется на Могучем :)


 
antonn ©   (2007-10-26 23:14) [33]

PREFETCHT0 - это SSE? встречал пару раз в коде, но не разбирался:)
пользуюсь всякими исходниками и справочником Зубкова С.В. "Ассемблер" в chm (к великому сожалению нет поиска по нему, зато русский и с картинками:)): http://desksoft.ru/index.php?downloads=attachments&id=34 (524Кб). pshufw в ней нет, странно...
+ метод научного тыка %)

все таки соврал, ММХ чуть быстрее 1,073832 против 1,10366 "голым кодом" :)


 
Pavia ©   (2007-10-27 00:14) [34]

PREFETCHT0. - это не SSE и не MMX

PREFETCHT- выбирать с упреждением. Чтобы не тратиться на загрузку данных в кэш сразу указываем что загрузить.

Насчет, справочника я использую мануэл от Intel, причем не самый последний. Так как последний разбит на два документа, а в не столь старых все в одном.


 
Sapersky   (2007-10-29 16:47) [35]

http://www.codenet.ru/cat/Applications/Optimizations/

Но на tommesani описание лучше, ИМХО. Учите буржуйский.
pshufw и т.п.- это enhanced MMX (или integer SSE), соответственно их часто помещают в раздел с SSE.

сделал этот альфаканал, но с ММХ чуть медленней, чем без него получилось

А чем всё-таки PMAXUB(W) не нравится? То, что она на 3/4 будет работать "вхолостую" - не имеет значения, гораздо важнее что не будет cmp/jump.



Страницы: 1 вся ветка

Форум: "Media";
Текущий архив: 2009.04.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.6 MB
Время: 0.007 c
2-1237228064
Elephon
2009-03-16 21:27
2009.04.26
Открытие файла


2-1236879849
motor666
2009-03-12 20:44
2009.04.26
СВЯЗНЫЕ ТАБЛИЦЫ. ПОМОГИТЕ С DBGRID


2-1237215031
пикассо
2009-03-16 17:50
2009.04.26
Что не так с utf8?


15-1235259659
Nic
2009-02-22 02:40
2009.04.26
TWebBrowser


15-1235424601
Юрий
2009-02-24 00:30
2009.04.26
С днем рождения ! 24 февраля 2009 вторник





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский