diff options
Diffstat (limited to 'prenderer.cpp')
-rw-r--r-- | prenderer.cpp | 665 |
1 files changed, 244 insertions, 421 deletions
diff --git a/prenderer.cpp b/prenderer.cpp index 58e1b22..aa44a5a 100644 --- a/prenderer.cpp +++ b/prenderer.cpp @@ -30,9 +30,9 @@ T_CompPosToLayerPos(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uin static v2 Transform_ScreenSpaceToLocal(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, - ui UI, ImVec2 ViewportMin, ImVec2 Point) + ImVec2 CompPos, ImVec2 CompZoom, ImVec2 ViewportMin, ImVec2 Point) { - v2 CompUV = ImGui_ScreenPointToCompUV(ViewportMin, UI.CompPos, UI.CompZoom, Point); + v2 CompUV = ImGui_ScreenPointToCompUV(ViewportMin, CompPos, CompZoom, Point); v2 LayerUV = T_CompUVToLayerUV(T, FileWidth, FileHeight, SourceWidth, SourceHeight, CompUV); return V2(LayerUV.x * SourceWidth, LayerUV.y * SourceHeight); } @@ -260,7 +260,26 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio static void RenderLayers(render_entry Entry) { - Fallback_RenderLayer(*(transform_info *)Entry.RenderData, Entry.OutputBuffer, Entry.RenderRegion); + switch (Entry.RenderType) + { + case render_type_main: + { + Fallback_RenderLayer(*(transform_info *)Entry.RenderData, Entry.OutputBuffer, Entry.RenderRegion); + } break; + case render_type_direct: + { + Assert(0); + // Fallback_RenderDirect(*(direct_info *)Entry.RenderData, Entry.OutputBuffer, Entry.RenderRegion); + } break; + case render_type_brush: + { + PaintTest_AVX2(*(brush_info *)Entry.RenderData, Entry.OutputBuffer, Entry.RenderRegion); + } break; + default: + { + Assert(0); + } + } #if 0 #if ARM Fallback_RenderLayer(RenderData->TransformInfo[i], RenderInfo->CompBuffer, RenderRegion); @@ -274,17 +293,17 @@ RenderLayers(render_entry Entry) { } static void -Renderer_Start(void *Data, void *OutputBuffer, rectangle RenderRegion) +Renderer_Start(void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion) { // CPU - Threading_BitmapOp(Data, OutputBuffer, RenderRegion); + Threading_BitmapOp(Data, OutputBuffer, RenderType, RenderRegion); } static void -Renderer_Check(bool32 *Test) +Renderer_Check(bool32 *Test, render_type RenderType) { // CPU - *Test = Threading_IsActive(); + *Test = Threading_IsActive(RenderType); } @@ -351,7 +370,6 @@ Transform_Calculate(project_state *State, memory *Memory, project_data *File, bl if (Points[i].x > MaxX) { MaxX = Points[i].x; } if (Points[i].y > MaxY) { MaxY = Points[i].y; } } - TransformInfo.XAxisPX = XLengthSq*XAxis.x; TransformInfo.XAxisPY = XLengthSq*XAxis.y; TransformInfo.YAxisPX = YLengthSq*YAxis.x; @@ -373,15 +391,137 @@ Transform_Calculate(project_state *State, memory *Memory, project_data *File, bl TransformInfo.OriginY = Origin.y; TransformInfo.BufferPitch = Comp->Width*Comp->BytesPerPixel; TransformInfo.LayerPitch = Width*BytesPerPixel; - TransformInfo.ClipRect = {MinX - (MinX & 3), MinY, MaxX + 1, MaxY + 1}; + TransformInfo.ClipRect = {MinX, MinY, MaxX, MaxY}; TransformInfo.IsAdjustment = Layer->IsAdjustment; return TransformInfo; } +// NOTE(fox): is this too ridiculous? i don't trust inline +#define Fallback_Blend() \ + switch (T.BlendMode)\ + {\ + case blend_normal:\ + {\ + } break;\ + case blend_multiply:\ + {\ + R_Blend = R_Dest * R_Col;\ + G_Blend = G_Dest * G_Col;\ + B_Blend = B_Dest * B_Col;\ + } break;\ + case blend_colorburn:\ + {\ + /* NOTE(fox): Padding to prevent actual crashing from zero division */ \ + R_Blend = 1.0f - ((1.0f - R_Dest) / (R_Col + 0.001f));\ + G_Blend = 1.0f - ((1.0f - G_Dest) / (G_Col + 0.001f));\ + B_Blend = 1.0f - ((1.0f - B_Dest) / (B_Col + 0.001f));\ + } break;\ + case blend_linearburn:\ + {\ + R_Blend = (R_Dest + R_Col) - 1.0f;\ + G_Blend = (G_Dest + G_Col) - 1.0f;\ + B_Blend = (B_Dest + B_Col) - 1.0f;\ + } break;\ + case blend_add:\ + {\ + R_Blend = R_Dest + R_Col;\ + G_Blend = G_Dest + G_Col;\ + B_Blend = B_Dest + B_Col;\ + } break;\ + case blend_screen:\ + {\ + R_Blend = 1.0f - ((1.0f - R_Dest) * (1.0f - R_Col));\ + G_Blend = 1.0f - ((1.0f - G_Dest) * (1.0f - G_Col));\ + B_Blend = 1.0f - ((1.0f - B_Dest) * (1.0f - B_Col));\ + } break;\ + case blend_overlay:\ + {\ + if (R_Dest < 0.5) {\ + R_Blend = 2.0f * R_Dest * R_Col;\ + } else {\ + R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col));\ + }\ + if (G_Dest < 0.5) {\ + G_Blend = 2.0f * G_Dest * G_Col;\ + } else {\ + G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col));\ + }\ + if (B_Dest < 0.5) {\ + B_Blend = 2.0f * B_Dest * B_Col;\ + } else {\ + B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col));\ + }\ + } break;\ + case blend_softlight:\ + {\ + /* using Pegtop's equation */ \ + R_Blend = ((1.0f - R_Col * 2) * R_Dest * R_Dest) + (R_Col * 2 * R_Dest);\ + G_Blend = ((1.0f - G_Col * 2) * G_Dest * G_Dest) + (G_Col * 2 * G_Dest);\ + B_Blend = ((1.0f - B_Col * 2) * B_Dest * B_Dest) + (B_Col * 2 * B_Dest);\ + } break;\ + case blend_hardlight:\ + {\ + if (R_Dest > 0.5) {\ + R_Blend = 2.0f * R_Dest * R_Col;\ + } else {\ + R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col));\ + }\ + if (G_Dest > 0.5) {\ + G_Blend = 2.0f * G_Dest * G_Col;\ + } else {\ + G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col));\ + }\ + if (B_Dest > 0.5) {\ + B_Blend = 2.0f * B_Dest * B_Col;\ + } else {\ + B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col));\ + }\ + } break;\ + case blend_subtract:\ + {\ + R_Blend = R_Dest - R_Col;\ + G_Blend = G_Dest - G_Col;\ + B_Blend = B_Dest - B_Col;\ + } break;\ + case blend_divide:\ + {\ + R_Blend = R_Dest / (R_Col + 0.001f);\ + G_Blend = G_Dest / (G_Col + 0.001f);\ + B_Blend = B_Dest / (B_Col + 0.001f);\ + } break;\ + case blend_difference:\ + {\ + if (R_Col - R_Dest > 0) {\ + R_Blend = R_Col - R_Dest;\ + } else {\ + R_Blend = R_Dest - R_Col;\ + }\ + if (G_Col - G_Dest > 0) {\ + G_Blend = G_Col - G_Dest;\ + } else {\ + G_Blend = G_Dest - G_Col;\ + }\ + if (B_Col - B_Dest > 0) {\ + B_Blend = B_Col - B_Dest;\ + } else {\ + B_Blend = B_Dest - B_Col;\ + }\ + } break;\ + }\ +\ + R_Blend = (R_Dest * (1.0f - LayerAlpha)) + (R_Blend * LayerAlpha);\ + G_Blend = (G_Dest * (1.0f - LayerAlpha)) + (G_Blend * LayerAlpha);\ + B_Blend = (B_Dest * (1.0f - LayerAlpha)) + (B_Blend * LayerAlpha);\ +\ + if (T.BlendMode == blend_normal)\ + A_Blend = A_Dest + LayerAlpha;\ + else\ + A_Blend = A_Dest;\ + static void -Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegion) +Fallback_RenderDirect(transform_info T, void *OutputBuffer, rectangle RenderRegion) { rectangle LayerBounds = ClipRectangle( T.ClipRect, RenderRegion); @@ -390,15 +530,84 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio for (int16 Y = LayerBounds.Min.y; Y < LayerBounds.Max.y; Y++) { - real32 StartVectorY = (real32)Y - T.OriginY; - for (int16 X = LayerBounds.Min.x; X < LayerBounds.Max.x; X++) { + uint16 LX = X; + uint16 LY = Y; + uint16 LXPlus = Ceil(X+1, (uint32)T.LayerWidth - 1); + uint16 LYPlus = Ceil(Y+1, (uint32)T.LayerHeight - 1); + + uint8 *TexPTR0 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LY) + (LX * (uint16)T.LayerBytesPerPixel)); + uint32 PixelA = *(uint32 *)TexPTR0; + + real32 TexRA = (real32)(*(uint32 *)(TexPTR0 + T.LayerBits.ByteOffset * 0) & T.LayerBits.MaskPixel) * T.LayerBits.Normalized; + real32 TexGA = (real32)(*(uint32 *)(TexPTR0 + T.LayerBits.ByteOffset * 1) & T.LayerBits.MaskPixel) * T.LayerBits.Normalized; + real32 TexBA = (real32)(*(uint32 *)(TexPTR0 + T.LayerBits.ByteOffset * 2) & T.LayerBits.MaskPixel) * T.LayerBits.Normalized; + real32 TexAA = (real32)(*(uint32 *)(TexPTR0 + T.LayerBits.ByteOffset * 3) & T.LayerBits.MaskPixel) * T.LayerBits.Normalized; + + real32 LayerAlpha = TexAA * 1; // brush opacity + + real32 R_Col = TexRA; + real32 G_Col = TexGA; + real32 B_Col = TexBA; + real32 A_Col = TexAA; + + real32 R_Blend = TexRA; + real32 G_Blend = TexGA; + real32 B_Blend = TexBA; + real32 A_Blend = TexAA; + + uint8 *DestPixel =((uint8 *)OutputBuffer + ((uint16)Y * (uint16)T.BufferPitch) + ((uint16)X * (uint16)T.BufferBytesPerPixel)); + + uint32 *R_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 0); + uint32 *G_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 1); + uint32 *B_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 2); + uint32 *A_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 3); + + if (LayerAlpha != 1.0f || T.BlendMode != blend_normal) { + + real32 R_Dest = (real32)(*R_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized; + real32 G_Dest = (real32)(*G_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized; + real32 B_Dest = (real32)(*B_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized; + real32 A_Dest = (real32)(*A_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized; + + Fallback_Blend(); + } + + uint32 R_Out = (uint32)(Normalize(R_Blend) * T.BufferBits.Bits); + uint32 G_Out = (uint32)(Normalize(G_Blend) * T.BufferBits.Bits); + uint32 B_Out = (uint32)(Normalize(B_Blend) * T.BufferBits.Bits); + uint32 A_Out = (uint32)(Normalize(A_Blend) * T.BufferBits.Bits); + + *R_DestAddress = (*R_DestAddress & ~T.BufferBits.MaskPixel) | R_Out; + *G_DestAddress = (*G_DestAddress & ~T.BufferBits.MaskPixel) | G_Out; + *B_DestAddress = (*B_DestAddress & ~T.BufferBits.MaskPixel) | B_Out; + *A_DestAddress = (*A_DestAddress & ~T.BufferBits.MaskPixel) | A_Out; + } + } +} +static void +Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegion) +{ + rectangle LayerBounds = ClipRectangle( T.ClipRect, RenderRegion); + + Assert(LayerBounds.Max.x <= T.BufferWidth); + Assert(LayerBounds.Max.y <= T.BufferHeight); + + for (int Y = LayerBounds.Min.y; Y < LayerBounds.Max.y; Y++) + { + real32 StartVectorY = (real32)Y - T.OriginY; + + for (int X = LayerBounds.Min.x; X < LayerBounds.Max.x; X++) + { real32 StartVectorX = X - T.OriginX; real32 U = (StartVectorX * T.XAxisPX) + (StartVectorY * T.XAxisPY); real32 V = (StartVectorX * T.YAxisPX) + (StartVectorY * T.YAxisPY); + if (X == T.BufferWidth) + int why = 0; + if (U < 1.0f && U >= 0.0f && V < 1.0f && V >= 0.0f) { real32 TexXFull = U * T.LayerWidth; @@ -418,15 +627,15 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio uint32 XLookup, YLookup, PixelToSeek; - uint16 LX = TexXInt; - uint16 LY = TexYInt; - uint16 LXPlus = Ceil(TexXInt+1, (uint32)T.LayerWidth - 1); - uint16 LYPlus = Ceil(TexYInt+1, (uint32)T.LayerHeight - 1); + uint32 LX = TexXInt; + uint32 LY = TexYInt; + uint32 LXPlus = Ceil(TexXInt+1, (uint32)T.LayerWidth - 1); + uint32 LYPlus = Ceil(TexYInt+1, (uint32)T.LayerHeight - 1); - uint8 *TexPTR0 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LY) + (LX * (uint16)T.LayerBytesPerPixel)); - uint8 *TexPTR1 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LY) + (LXPlus * (uint16)T.LayerBytesPerPixel)); - uint8 *TexPTR2 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LYPlus) + (LX * (uint16)T.LayerBytesPerPixel)); - uint8 *TexPTR3 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LYPlus) + (LXPlus * (uint16)T.LayerBytesPerPixel)); + uint8 *TexPTR0 = ((uint8 *)T.SourceBuffer + ((uint32)T.LayerPitch * LY) + (LX * (uint32)T.LayerBytesPerPixel)); + uint8 *TexPTR1 = ((uint8 *)T.SourceBuffer + ((uint32)T.LayerPitch * LY) + (LXPlus * (uint32)T.LayerBytesPerPixel)); + uint8 *TexPTR2 = ((uint8 *)T.SourceBuffer + ((uint32)T.LayerPitch * LYPlus) + (LX * (uint32)T.LayerBytesPerPixel)); + uint8 *TexPTR3 = ((uint8 *)T.SourceBuffer + ((uint32)T.LayerPitch * LYPlus) + (LXPlus * (uint32)T.LayerBytesPerPixel)); uint32 PixelA = *(uint32 *)TexPTR0; uint32 PixelB = *(uint32 *)TexPTR1; @@ -515,12 +724,13 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio real32 B_Blend = B_Col; real32 A_Blend = A_Col; - uint8 *DestPixel =((uint8 *)OutputBuffer + ((uint16)Y * (uint16)T.BufferPitch) + ((uint16)X * (uint16)T.BufferBytesPerPixel)); + uint8 *DestPixel =((uint8 *)OutputBuffer + ((uint32)Y * (uint32)T.BufferPitch) + ((uint32)X * (uint32)T.BufferBytesPerPixel)); + Assert(X != (T.BufferWidth)); - uint32 *R_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 0); - uint32 *G_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 1); - uint32 *B_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 2); - uint32 *A_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 3); + uint8 *R_DestAddress = (DestPixel + T.BufferBits.ByteOffset * 0); + uint8 *G_DestAddress = (DestPixel + T.BufferBits.ByteOffset * 1); + uint8 *B_DestAddress = (DestPixel + T.BufferBits.ByteOffset * 2); + uint8 *A_DestAddress = (DestPixel + T.BufferBits.ByteOffset * 3); if (LayerAlpha != 1.0f || T.BlendMode != blend_normal) { @@ -529,136 +739,18 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio real32 B_Dest = (real32)(*B_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized; real32 A_Dest = (real32)(*A_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized; - switch (T.BlendMode) - { - case blend_normal: - { - } break; - case blend_multiply: - { - R_Blend = R_Dest * R_Col; - G_Blend = G_Dest * G_Col; - B_Blend = B_Dest * B_Col; - } break; - case blend_colorburn: - { - // NOTE(fox): Padding to prevent actual crashing from zero division - R_Blend = 1.0f - ((1.0f - R_Dest) / (R_Col + 0.001f)); - G_Blend = 1.0f - ((1.0f - G_Dest) / (G_Col + 0.001f)); - B_Blend = 1.0f - ((1.0f - B_Dest) / (B_Col + 0.001f)); - } break; - case blend_linearburn: - { - R_Blend = (R_Dest + R_Col) - 1.0f; - G_Blend = (G_Dest + G_Col) - 1.0f; - B_Blend = (B_Dest + B_Col) - 1.0f; - } break; - case blend_add: - { - R_Blend = R_Dest + R_Col; - G_Blend = G_Dest + G_Col; - B_Blend = B_Dest + B_Col; - } break; - case blend_screen: - { - R_Blend = 1.0f - ((1.0f - R_Dest) * (1.0f - R_Col)); - G_Blend = 1.0f - ((1.0f - G_Dest) * (1.0f - G_Col)); - B_Blend = 1.0f - ((1.0f - B_Dest) * (1.0f - B_Col)); - } break; - case blend_overlay: - { - if (R_Dest < 0.5) { - R_Blend = 2.0f * R_Dest * R_Col; - } else { - R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col)); - } - if (G_Dest < 0.5) { - G_Blend = 2.0f * G_Dest * G_Col; - } else { - G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col)); - } - if (B_Dest < 0.5) { - B_Blend = 2.0f * B_Dest * B_Col; - } else { - B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col)); - } - } break; - case blend_softlight: - { - // using Pegtop's equation - R_Blend = ((1.0f - R_Col * 2) * R_Dest * R_Dest) + (R_Col * 2 * R_Dest); - G_Blend = ((1.0f - G_Col * 2) * G_Dest * G_Dest) + (G_Col * 2 * G_Dest); - B_Blend = ((1.0f - B_Col * 2) * B_Dest * B_Dest) + (B_Col * 2 * B_Dest); - } break; - case blend_hardlight: - { - if (R_Dest > 0.5) { - R_Blend = 2.0f * R_Dest * R_Col; - } else { - R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col)); - } - if (G_Dest > 0.5) { - G_Blend = 2.0f * G_Dest * G_Col; - } else { - G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col)); - } - if (B_Dest > 0.5) { - B_Blend = 2.0f * B_Dest * B_Col; - } else { - B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col)); - } - } break; - case blend_subtract: - { - R_Blend = R_Dest - R_Col; - G_Blend = G_Dest - G_Col; - B_Blend = B_Dest - B_Col; - } break; - case blend_divide: - { - R_Blend = R_Dest / (R_Col + 0.001f); - G_Blend = G_Dest / (G_Col + 0.001f); - B_Blend = B_Dest / (B_Col + 0.001f); - } break; - case blend_difference: - { - if (R_Col - R_Dest > 0) { - R_Blend = R_Col - R_Dest; - } else { - R_Blend = R_Dest - R_Col; - } - if (G_Col - G_Dest > 0) { - G_Blend = G_Col - G_Dest; - } else { - G_Blend = G_Dest - G_Col; - } - if (B_Col - B_Dest > 0) { - B_Blend = B_Col - B_Dest; - } else { - B_Blend = B_Dest - B_Col; - } - } break; - } - - R_Blend = (R_Dest * (1.0f - LayerAlpha)) + (R_Blend * LayerAlpha); - G_Blend = (G_Dest * (1.0f - LayerAlpha)) + (G_Blend * LayerAlpha); - B_Blend = (B_Dest * (1.0f - LayerAlpha)) + (B_Blend * LayerAlpha); - - if (T.BlendMode == blend_normal) - A_Blend = A_Dest + LayerAlpha; - else - A_Blend = A_Dest; + Fallback_Blend(); } - uint32 R_Out = (uint32)(Normalize(R_Blend) * T.BufferBits.Bits); - uint32 G_Out = (uint32)(Normalize(G_Blend) * T.BufferBits.Bits); - uint32 B_Out = (uint32)(Normalize(B_Blend) * T.BufferBits.Bits); - uint32 A_Out = (uint32)(Normalize(A_Blend) * T.BufferBits.Bits); + uint8 R_Out = (uint8)(Normalize(R_Blend) * T.BufferBits.Bits); + uint8 G_Out = (uint8)(Normalize(G_Blend) * T.BufferBits.Bits); + uint8 B_Out = (uint8)(Normalize(B_Blend) * T.BufferBits.Bits); + uint8 A_Out = (uint8)(Normalize(A_Blend) * T.BufferBits.Bits); - *R_DestAddress = (*R_DestAddress & ~T.BufferBits.MaskPixel) | R_Out; - *G_DestAddress = (*G_DestAddress & ~T.BufferBits.MaskPixel) | G_Out; - *B_DestAddress = (*B_DestAddress & ~T.BufferBits.MaskPixel) | B_Out; - *A_DestAddress = (*A_DestAddress & ~T.BufferBits.MaskPixel) | A_Out; + *R_DestAddress = R_Out; + *G_DestAddress = G_Out; + *B_DestAddress = B_Out; + *A_DestAddress = A_Out; // *R_DestAddress = 255; // *G_DestAddress = 255; // *B_DestAddress = 255; @@ -1781,274 +1873,5 @@ SSE2_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion) } } - -#endif - -static void -Fallback_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion) -{ - rectangle LayerBounds = ClipRectangle( T.ClipRect, RenderRegion); - - Assert(LayerBounds.Max.x <= Buffer->Width); - Assert(LayerBounds.Max.y <= Buffer->Height); - - uint16 WidthP, HeightP; - Bitmap_CalcPackedDimensions(Buffer->Width, Buffer->Height, &WidthP, &HeightP); - - real32 Normalized255 = 1 / 255.0f; - - for (int16 Y = LayerBounds.Min.y; Y < LayerBounds.Max.y; Y++) - { - real32 StartVectorY = (real32)Y - T.OriginY; - - for (int16 X = LayerBounds.Min.x; X < LayerBounds.Max.x; X++) - { - - real32 StartVectorX = X - T.OriginX; - real32 U = (StartVectorX * T.XAxisPX) + (StartVectorY * T.XAxisPY); - real32 V = (StartVectorX * T.YAxisPX) + (StartVectorY * T.YAxisPY); - - if (U < 1.0f && U >= 0.0f && V < 1.0f && V >= 0.0f) { - - real32 TexXFull = U * T.LayerWidth; - uint32 TexXInt = (uint32)TexXFull; - real32 TexX = TexXFull - TexXInt; - - real32 TexYFull = V * T.LayerHeight; - uint32 TexYInt = (uint32)TexYFull; - real32 TexY = TexYFull - TexYInt; - - real32 TexXInv = 1 - TexX; - real32 TexYInv = 1 - TexY; - real32 TexBothXInv = TexXInv * TexY; - real32 TexBothYInv = TexX * TexYInv; - real32 TexBoth = TexY * TexX; - real32 TexBothInv = TexXInv * TexYInv; - - uint32 XLookup, YLookup, PixelToSeek; - - uint16 LX = TexXInt; - uint16 LY = TexYInt; - uint16 LXPlus = Ceil(TexXInt+1, (uint32)T.LayerWidth - 1); - uint16 LYPlus = Ceil(TexYInt+1, (uint32)T.LayerHeight - 1); - -#if PACKEDRGB - // TODO(fox): Be careful with the BytesPerPixel here! It's the - // buffer's, not the layer's (currently everything is 4 bytes - // per pixel). - XLookup = (LX >> 2)*16 + (LX % 4); - YLookup = (LY >> 2)*(T.FullLayerWidth*4) + (LY % 4)*4; - PixelToSeek = XLookup + YLookup; - uint32 PixelA = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel); - - XLookup = (LXPlus >> 2)*16 + (LXPlus % 4); - YLookup = (LY >> 2)*(T.FullLayerWidth*4) + (LY % 4)*4; - PixelToSeek = XLookup + YLookup; - uint32 PixelB = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel); - - XLookup = (LX >> 2)*16 + (LX % 4); - YLookup = (LYPlus >> 2)*(T.FullLayerWidth*4) + (LYPlus % 4)*4; - PixelToSeek = XLookup + YLookup; - uint32 PixelC = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel); - - XLookup = (LXPlus >> 2)*16 + (LXPlus % 4); - YLookup = (LYPlus >> 2)*(T.FullLayerWidth*4) + (LYPlus % 4)*4; - PixelToSeek = XLookup + YLookup; - uint32 PixelD = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel); - - XLookup = (X >> 2)*16 + (X % 4); - YLookup = (Y >> 2)*(WidthP*4) + (Y % 4)*4; - PixelToSeek = XLookup + YLookup; - uint32 *Pixel = (uint32 *)((uint8 *)Buffer->PackedBuffer + PixelToSeek*Buffer->BytesPerPixel); - -#else - uint8 *TexPTR0 = ((uint8 *)T.SourceBuffer + (uint16)T.LayerPitch*LY + LX*Buffer->BytesPerPixel); - uint8 *TexPTR1 = ((uint8 *)T.SourceBuffer + (uint16)T.LayerPitch*LY + LXPlus*Buffer->BytesPerPixel); - uint8 *TexPTR2 = ((uint8 *)T.SourceBuffer + (uint16)T.LayerPitch*LYPlus + LX*Buffer->BytesPerPixel); - uint8 *TexPTR3 = ((uint8 *)T.SourceBuffer + (uint16)T.LayerPitch*LYPlus + LXPlus*Buffer->BytesPerPixel); - - uint32 PixelA = *(uint32 *)TexPTR0; - uint32 PixelB = *(uint32 *)TexPTR1; - uint32 PixelC = *(uint32 *)TexPTR2; - uint32 PixelD = *(uint32 *)TexPTR3; - - uint32 *Pixel = (uint32 *)((uint8 *)Buffer->UnpackedBuffer + Y*T.BufferPitch + X*Buffer->BytesPerPixel); #endif - real32 TexRA = (real32)(PixelA & 0xFF) * Normalized255; - real32 TexRB = (real32)(PixelB & 0xFF) * Normalized255; - real32 TexRC = (real32)(PixelC & 0xFF) * Normalized255; - real32 TexRD = (real32)(PixelD & 0xFF) * Normalized255; - - real32 TexGA = (real32)((PixelA >> 8) & 0xFF) * Normalized255; - real32 TexGB = (real32)((PixelB >> 8) & 0xFF) * Normalized255; - real32 TexGC = (real32)((PixelC >> 8) & 0xFF) * Normalized255; - real32 TexGD = (real32)((PixelD >> 8) & 0xFF) * Normalized255; - - real32 TexBA = (real32)((PixelA >> 16) & 0xFF) * Normalized255; - real32 TexBB = (real32)((PixelB >> 16) & 0xFF) * Normalized255; - real32 TexBC = (real32)((PixelC >> 16) & 0xFF) * Normalized255; - real32 TexBD = (real32)((PixelD >> 16) & 0xFF) * Normalized255; - - real32 TexAA = (real32)((PixelA >> 24) & 0xFF) * Normalized255; - real32 TexAB = (real32)((PixelB >> 24) & 0xFF) * Normalized255; - real32 TexAC = (real32)((PixelC >> 24) & 0xFF) * Normalized255; - real32 TexAD = (real32)((PixelD >> 24) & 0xFF) * Normalized255; - - real32 R_Col = (TexBothInv * TexRA) + (TexBothYInv * TexRB) - + (TexBothXInv * TexRC) + (TexBoth * TexRD); - real32 G_Col = (TexBothInv * TexGA) + (TexBothYInv * TexGB) - + (TexBothXInv * TexGC) + (TexBoth * TexGD); - real32 B_Col = (TexBothInv * TexBA) + (TexBothYInv * TexBB) - + (TexBothXInv * TexBC) + (TexBoth * TexBD); - real32 A_Col = (TexBothInv * TexAA) + (TexBothYInv * TexAB) - + (TexBothXInv * TexAC) + (TexBoth * TexAD); - - real32 LayerAlpha = A_Col * T.LayerOpacity; - - real32 R_Blend = R_Col; - real32 G_Blend = G_Col; - real32 B_Blend = B_Col; - real32 A_Blend = A_Col; - - if (LayerAlpha != 1.0f || T.BlendMode != blend_normal) { - - real32 R_Dest = (real32)((*Pixel >> 0) & 0xFF) * Normalized255; - real32 G_Dest = (real32)((*Pixel >> 8) & 0xFF) * Normalized255; - real32 B_Dest = (real32)((*Pixel >> 16) & 0xFF) * Normalized255; - real32 A_Dest = (real32)((*Pixel >> 24) & 0xFF) * Normalized255; - - switch (T.BlendMode) - { - case blend_normal: - { - } break; - case blend_multiply: - { - R_Blend = R_Dest * R_Col; - G_Blend = G_Dest * G_Col; - B_Blend = B_Dest * B_Col; - } break; - case blend_colorburn: - { - // NOTE(fox): Padding to prevent actual crashing from zero division - R_Blend = 1.0f - ((1.0f - R_Dest) / (R_Col + 0.001f)); - G_Blend = 1.0f - ((1.0f - G_Dest) / (G_Col + 0.001f)); - B_Blend = 1.0f - ((1.0f - B_Dest) / (B_Col + 0.001f)); - } break; - case blend_linearburn: - { - R_Blend = (R_Dest + R_Col) - 1.0f; - G_Blend = (G_Dest + G_Col) - 1.0f; - B_Blend = (B_Dest + B_Col) - 1.0f; - } break; - case blend_add: - { - R_Blend = R_Dest + R_Col; - G_Blend = G_Dest + G_Col; - B_Blend = B_Dest + B_Col; - } break; - case blend_screen: - { - R_Blend = 1.0f - ((1.0f - R_Dest) * (1.0f - R_Col)); - G_Blend = 1.0f - ((1.0f - G_Dest) * (1.0f - G_Col)); - B_Blend = 1.0f - ((1.0f - B_Dest) * (1.0f - B_Col)); - } break; - case blend_overlay: - { - if (R_Dest < 0.5) { - R_Blend = 2.0f * R_Dest * R_Col; - } else { - R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col)); - } - if (G_Dest < 0.5) { - G_Blend = 2.0f * G_Dest * G_Col; - } else { - G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col)); - } - if (B_Dest < 0.5) { - B_Blend = 2.0f * B_Dest * B_Col; - } else { - B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col)); - } - } break; - case blend_softlight: - { - // using Pegtop's equation - R_Blend = ((1.0f - R_Col * 2) * R_Dest * R_Dest) + (R_Col * 2 * R_Dest); - G_Blend = ((1.0f - G_Col * 2) * G_Dest * G_Dest) + (G_Col * 2 * G_Dest); - B_Blend = ((1.0f - B_Col * 2) * B_Dest * B_Dest) + (B_Col * 2 * B_Dest); - } break; - case blend_hardlight: - { - if (R_Dest > 0.5) { - R_Blend = 2.0f * R_Dest * R_Col; - } else { - R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col)); - } - if (G_Dest > 0.5) { - G_Blend = 2.0f * G_Dest * G_Col; - } else { - G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col)); - } - if (B_Dest > 0.5) { - B_Blend = 2.0f * B_Dest * B_Col; - } else { - B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col)); - } - } break; - case blend_subtract: - { - R_Blend = R_Dest - R_Col; - G_Blend = G_Dest - G_Col; - B_Blend = B_Dest - B_Col; - } break; - case blend_divide: - { - R_Blend = R_Dest / (R_Col + 0.001f); - G_Blend = G_Dest / (G_Col + 0.001f); - B_Blend = B_Dest / (B_Col + 0.001f); - } break; - case blend_difference: - { - if (R_Col - R_Dest > 0) { - R_Blend = R_Col - R_Dest; - } else { - R_Blend = R_Dest - R_Col; - } - if (G_Col - G_Dest > 0) { - G_Blend = G_Col - G_Dest; - } else { - G_Blend = G_Dest - G_Col; - } - if (B_Col - B_Dest > 0) { - B_Blend = B_Col - B_Dest; - } else { - B_Blend = B_Dest - B_Col; - } - } break; - } - - R_Blend = (R_Dest * (1.0f - LayerAlpha)) + (R_Blend * LayerAlpha); - G_Blend = (G_Dest * (1.0f - LayerAlpha)) + (G_Blend * LayerAlpha); - B_Blend = (B_Dest * (1.0f - LayerAlpha)) + (B_Blend * LayerAlpha); - - if (T.BlendMode == blend_normal) - A_Blend = A_Dest + LayerAlpha; - else - A_Blend = A_Dest; - } - - uint8 R_Out = (uint8)(Normalize(R_Blend) * 255.0f); - uint8 G_Out = (uint8)(Normalize(G_Blend) * 255.0f); - uint8 B_Out = (uint8)(Normalize(B_Blend) * 255.0f); - uint8 A_Out = (uint8)(Normalize(A_Blend) * 255.0f); - - *Pixel = ((A_Out << 24) | - (B_Out << 16) | - (G_Out << 8) | - (R_Out << 0)); - } - } - } -} #endif |