
 /* SD_BufferSubs.c
    - GfxBuffer functions of ECS.svdriver -
    (c) 1990-95 by Andreas R. Kleinert
    Last changes : 06.05.1995
 */

#include "svdriver.h"

ULONG __saveds __asm SVD_SetGfxBuffer(      register __a1 struct SVDriverHandle *SVDriverHandle_a1, register __a2 struct SV_GfxBuffer *buffer, register __a3 ULONG future);
ULONG __saveds __asm SVD_DisplayGfxBuffer(  register __a1 struct SVDriverHandle *SVDriverHandle_a1, register __a2 ULONG future);

ULONG __saveds __stdargs SVLI_OpenDispScreen(struct SVDriverHandle *SVDriverHandle, struct SV_GfxBuffer *dispgfx);
ULONG __saveds __stdargs SVLI_SetScreenPalette(struct SV_GfxBuffer *dispgfx, struct Screen *screen, long colornum);

ULONG __saveds __stdargs IsHamBuffer(struct SV_GfxBuffer *gfxb);
ULONG __saveds __stdargs IsEhbBuffer(struct SV_GfxBuffer *gfxb);
ULONG __saveds __stdargs ComputeMode(struct SV_GfxBuffer *gfxb);

void __saveds __stdargs SVLI_ControlPads(ULONG *rtg);

struct SVP_OperatorNode * __saveds __stdargs SVLI_GetOperator24(void);
ULONG __saveds __stdargs SVLI_Do24BitOperation(struct SVDriverHandle *SVDriverHandle, struct SV_GfxBuffer *source, struct SV_GfxBuffer **dest, struct SVP_OperatorNode *op);
void __saveds __stdargs SVLI_Free24BitOperator(struct SVDriverHandle *SVDriverHandle);


/* *************************************************** */
/* *						     * */
/* * SVD_SetGfxBuffer :                              * */
/* *						     * */
/* *************************************************** */

ULONG __saveds __asm SVD_SetGfxBuffer(  register __a1 struct SVDriverHandle *SVDriverHandle_a1, register __a2 struct SV_GfxBuffer *buffer, register __a3 ULONG future)
{
 struct SVDriverHandle *SVDriverHandle = SVDriverHandle_a1;
 ULONG retval = SVERR_NO_ERROR;

 if(!SVDriverHandle) return(SVERR_NO_HANDLE);

 if(!buffer) return(SVERR_ILLEGAL_ACCESS);

 SVDriverHandle->ah_SV_GfxBuffer = buffer;

 return(retval);
}

/* *************************************************** */
/* *						     * */
/* * SVD_DisplayGfxBuffer :                          * */
/* *						     * */
/* *************************************************** */

ULONG __saveds __asm SVD_DisplayGfxBuffer(  register __a1 struct SVDriverHandle *SVDriverHandle_a1, register __a2 ULONG future)
{
 struct SVDriverHandle *SVDriverHandle = SVDriverHandle_a1;
 ULONG retval = SVERR_NO_ERROR;
 ULONG width, height, depth, colnum, linebytes, bmpwidth, j;
 UBYTE *buffer, *bufferptr, *planeptr;
 struct SV_GfxBuffer *dispgfx;

 struct RastPort *rp;
 struct BitMap	 *bm;
 struct ViewPort *vp;

 if(!SVDriverHandle) return(SVERR_ILLEGAL_ACCESS);


 dispgfx = SVDriverHandle->ah_SV_GfxBuffer;

 if(!dispgfx)                                              return(SVERR_ILLEGAL_ACCESS);
 if(!dispgfx->svgfx_Buffer)                                return(SVERR_ILLEGAL_ACCESS);
 if(dispgfx->svgfx_BufferType > SVGFX_BUFFERTYPE_ONEPLANE) return(SVERR_ACTION_NOT_SUPPORTED);


 /* Check whether and how to operate on 24 Bit Data and maybe, do it */

 if(dispgfx->svgfx_ColorDepth == 24)  /* check, whether to operator on 24 Bit graphics ... */
  {
   struct SVP_OperatorNode *op;
   struct SV_GfxBuffer *newdispgfx = N;

   if(dispgfx->svgfx_BufferType != SVGFX_BUFFERTYPE_ONEPLANE) return(SVERR_ACTION_NOT_SUPPORTED);
   
   op = SVLI_GetOperator24();
   if(!op) return(SVERR_UNKNOWN_PARAMETERS);

   retval = SVLI_Do24BitOperation(SVDriverHandle, dispgfx, &newdispgfx, op);
   if(!retval) if(newdispgfx) dispgfx = newdispgfx;
  }else
  {
   if(dispgfx->svgfx_BufferType == SVGFX_BUFFERTYPE_BITPLANE)
    {
     if(dispgfx->svgfx_ColorDepth <= 8)
      {
       ULONG rtg = FALSE;

       SVLI_ControlPads(&rtg);
       if(rtg)
        {
         retval = SVSUP_BitPlaneToOnePlane8(SVDriverHandle->ah_SV_GfxBuffer, &SVDriverHandle->ah_TmpGfxBuffer);
         if(!retval) dispgfx = SVDriverHandle->ah_TmpGfxBuffer;
        }
      }else retval = SVERR_UNKNOWN_PARAMETERS;
    }
  }

 if(retval) return(retval);

 bufferptr = buffer = dispgfx->svgfx_Buffer;
 if(!buffer) return(SVERR_ILLEGAL_ACCESS);


 /* Open Screen */

 if(!SVLI_OpenDispScreen(SVDriverHandle, dispgfx)) return(SVERR_NO_SCREEN);

 rp = (struct RastPort *) &(SVDriverHandle->ah_Screen->RastPort);
 bm = (struct BitMap   *) SVDriverHandle->ah_Screen->RastPort.BitMap;
 vp = (struct ViewPort *) &(SVDriverHandle->ah_Screen->ViewPort);

 width     = dispgfx->svgfx_Width;
 height    = dispgfx->svgfx_Height;
 depth     = dispgfx->svgfx_ColorDepth;
 colnum    = 1 << depth;

 bmpwidth = ((width + 31) >> 5) << 5;

 if(dispgfx->svgfx_BufferType == SVGFX_BUFFERTYPE_BITPLANE)
       linebytes = (long) dispgfx->svgfx_BytesPerLine;
  else linebytes = (long) bm->BytesPerRow;


 /* Read Palette */

 SVLI_SetScreenPalette(dispgfx, SVDriverHandle->ah_Screen, colnum);


 /* Decoding */

 planeptr  = (UBYTE *) N;

 if(dispgfx->svgfx_BufferType == SVGFX_BUFFERTYPE_BITPLANE)
  {
   if(linebytes == bm->BytesPerRow)
    {
     ULONG prod_1 = height * linebytes;

     for(j=0;j<depth;j++) CopyMem(bufferptr + j*prod_1, bm->Planes[j], prod_1);
    }else
    {
              ULONG copybytes, pskipbytes, buf_ptradd1;
     register ULONG i, j;
     register UBYTE *bptr, *pptr;

     pskipbytes = bm->BytesPerRow;

     if(pskipbytes < linebytes) copybytes = pskipbytes;
      else                      copybytes = linebytes;

     buf_ptradd1 = height*linebytes;

     for(j=0;j<depth;j++)
      {
       bptr = (UBYTE *) bufferptr + (buf_ptradd1 * j);
       pptr = (UBYTE *) bm->Planes[j];

       for(i=0; i<height; i++)
        {
         CopyMem(bptr, pptr, copybytes);

         bptr += linebytes;
         pptr += pskipbytes;
        }
      }
    }
  }

 if(dispgfx->svgfx_BufferType == SVGFX_BUFFERTYPE_ONEPLANE)
  {
   if(depth <= 8)
    {
     /* Maybe, there are Graphic Cards, which allow 8 Bits colordepth
        via an intuition-compatible AGA-emulation, but nevertheless
        we cannot use V39-functions as in AGA.svdriver !!!
     */

     struct RastPort *tmp_rp;
     UBYTE           *bptr;
     UBYTE           *linebuffer;
     UWORD            i, j;

     linebuffer = (APTR) AllocVec(width, MEMF_CLEAR|MEMF_PUBLIC);
     if(linebuffer)
      {
       tmp_rp = (APTR) AllocVec(sizeof(struct RastPort), MEMF_CLEAR|MEMF_PUBLIC);
       if(tmp_rp)
        {
         InitRastPort(tmp_rp);

         tmp_rp->BitMap = AllocVec(sizeof(struct BitMap), MEMF_CLEAR|MEMF_PUBLIC);
         if(tmp_rp->BitMap)
          {
           InitBitMap(tmp_rp->BitMap, depth, bmpwidth, 1);

           for(i=0; i<depth; i++)
            {
             tmp_rp->BitMap->Planes[i] = (APTR) AllocRaster(bmpwidth, 1);
             if(!tmp_rp->BitMap->Planes[i])
              {
               retval = SVERR_NO_MEMORY;

               break;
              }
            }

           if(!retval)
            {
             ULONG wm8 = (width>>3)<<3;

             bptr = bufferptr;

             for(j=0; j<height; j++, bptr+=width)
              {
               CopyMem(bptr, linebuffer, width);

               WritePixelLine8(rp, 0, j, wm8, linebuffer, tmp_rp);
              }
            }

           for(i=0; i<8; i++) if(tmp_rp->BitMap->Planes[i]) FreeRaster(tmp_rp->BitMap->Planes[i], bmpwidth, 1);

           FreeVec(tmp_rp->BitMap);
          }else retval = SVERR_NO_MEMORY;

         FreeVec(tmp_rp);
        }else retval = SVERR_NO_MEMORY;

       FreeVec(linebuffer);

      }else retval = SVERR_NO_MEMORY;

    }else
    {
     /* Insert code for handling color depths > 8
        (future AGA or AAA features ?)
     */

     retval = SVERR_UNKNOWN_PARAMETERS;
    }
  }

 SVLI_Free24BitOperator(SVDriverHandle); /* if any */

 ScreenToFront(SVDriverHandle->ah_Screen);

 return(retval);
}

/* *************************************************** */
/* *						     * */
/* * SVLI_OpenDispScreen : Open Screen as needed     * */
/* *						     * */
/* *************************************************** */

struct TextAttr __aligned topazfont = { (STRPTR) "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT };

ULONG __saveds __stdargs SVLI_OpenDispScreen(struct SVDriverHandle *SVDriverHandle, struct SV_GfxBuffer *dispgfx)
{
 ULONG ai_width, ai_height, ai_depth, ai_mode_id;
 struct Rectangle __aligned rect;

 if(!dispgfx) return(FALSE);


 /* Get and set Standard Screen Dimensions */

 ai_width   = dispgfx->svgfx_Width;
 ai_height  = dispgfx->svgfx_Height;
 ai_depth   = dispgfx->svgfx_ColorDepth;
 ai_mode_id = ComputeMode(dispgfx);

 /* Get and/or set Screen, Window and IDCMP Flags */

 if(!SVDriverHandle->ah_ScreenType)  SVDriverHandle->ah_ScreenType  = CUSTOMSCREEN;
 if(!SVDriverHandle->ah_WindowIDCMP) SVDriverHandle->ah_WindowIDCMP = IDCMP_MOUSEBUTTONS | IDCMP_VANILLAKEY;
 if(!SVDriverHandle->ah_WindowFlags) SVDriverHandle->ah_WindowFlags = WFLG_BACKDROP | WFLG_BORDERLESS | WFLG_NOCAREREFRESH | WFLG_SIMPLE_REFRESH;

 if(!QueryOverscan(ai_mode_id, &rect, OSCAN_TEXT))
  {
   rect.MinX = 0;
   rect.MaxX = ai_width;
   rect.MinY = 0;
   rect.MaxY = ai_height;
  }

 /* Open Screen like needed for SVD Displaying */

 SVDriverHandle->ah_Screen = OpenScreenTags( NULL, SA_Left,        0,
                         			   SA_Top,	   0,
                        			   SA_Width,	   ai_width,
				                   SA_Height,	   ai_height,
				                   SA_Depth,	   ai_depth,
				                   SA_Font,	  &topazfont,
				                   SA_Type,	   SVDriverHandle->ah_ScreenType,
				                   SA_DisplayID,   ai_mode_id,
				                   SA_Title,	   "Please wait ...",
				                   SA_AutoScroll,  TRUE,
				                   SA_DClip,       &rect,
				                   SA_Behind,      TRUE,
				                   TAG_END );

 if(!SVDriverHandle->ah_Screen) return(FALSE);


 /* Open Window like needed for SVD Displaying */

 SVDriverHandle->ah_Window = OpenWindowTags(N,
			    WA_Left,	     0,
			    WA_Top,	     0,
			    WA_Width,	     SVDriverHandle->ah_Screen->Width,
			    WA_Height,	     SVDriverHandle->ah_Screen->Height,
			    WA_DetailPen,    1,
			    WA_BlockPen,     2,
			    WA_IDCMP,	     SVDriverHandle->ah_WindowIDCMP,
			    WA_Flags,	     SVDriverHandle->ah_WindowFlags,
			    WA_CustomScreen, SVDriverHandle->ah_Screen,
			    TAG_END,	     N);

 if(!SVDriverHandle->ah_Window)
  {
   CloseScreen(SVDriverHandle->ah_Screen); SVDriverHandle->ah_Screen = N;

   return(FALSE);
  }

 ActivateWindow(SVDriverHandle->ah_Window);

 return(TRUE);
}

/* *************************************************** */
/* *						     * */
/* * SVLI_SetScreenPalette : ColorMap (RGB8/RGB 32)  * */
/* *						     * */
/* *************************************************** */

ULONG __saveds __stdargs SVLI_SetScreenPalette(struct SV_GfxBuffer *dispgfx, struct Screen *screen, long colornum)
{
 struct ViewPort *vp;
 long i;

 if(dispgfx && screen)
  {
   vp = (struct ViewPort *) &(screen->ViewPort);

        if( (colornum == 64) && IsEhbBuffer(dispgfx) ) colornum = 32;
   else if( (colornum == 64) && IsHamBuffer(dispgfx) ) colornum = 16;

   if(OS_VER < 39)
    {
     /* Standard / ECS "4 Bit of 12 Bit" Colors (RGB4) */

     for(i=0;i<colornum;i++) SetRGB4(vp, i, dispgfx->svgfx_Colors[i][0]>>4, dispgfx->svgfx_Colors[i][1]>>4, dispgfx->svgfx_Colors[i][2]>>4);
    }else
    {
     /* AGA "8 Bit of 32 Bit" Colors (RGB32) */

     ULONG r,g,b;

     for(i=0;i<colornum;i++)
      {
       r  = (ULONG) dispgfx->svgfx_Colors[i][0];
       r |= (r<<24 | r<<16 | r<<8);

       g  = (ULONG) dispgfx->svgfx_Colors[i][1];
       g |= (g<<24 | g<<16 | g<<8);

       b  = (ULONG) dispgfx->svgfx_Colors[i][2];
       b |= (b<<24 | b<<16 | b<<8);

       SetRGB32(vp, i, r, g, b);
      }
    }
  }

 return(FALSE);
}

ULONG __saveds __stdargs IsHamBuffer(struct SV_GfxBuffer *gfxb)
{
 ULONG isham = FALSE;

 if(gfxb->svgfx_Version > 1) if(gfxb->svgfx_NativeDIPF & DIPF_IS_HAM) isham = TRUE;
 if(!isham)                  if(gfxb->svgfx_ViewMode32 & HAM_KEY)     isham = TRUE;

 return(isham);
}

ULONG __saveds __stdargs IsEhbBuffer(struct SV_GfxBuffer *gfxb)
{
 ULONG isehb = FALSE;

 if(gfxb->svgfx_Version > 1) if(gfxb->svgfx_NativeDIPF & DIPF_IS_EXTRAHALFBRITE) isehb = TRUE;
 if(!isehb)                  if(gfxb->svgfx_ViewMode32 & EXTRAHALFBRITE_KEY)     isehb = TRUE;

 return(isehb);
}

ULONG __saveds __stdargs ComputeMode(struct SV_GfxBuffer *gfxb)
{
 if( IsHamBuffer(gfxb) ) return(gfxb->svgfx_ViewMode32 | HAM_KEY);
 if( IsEhbBuffer(gfxb) ) return(gfxb->svgfx_ViewMode32 | EXTRAHALFBRITE_KEY);

 return(gfxb->svgfx_ViewMode32);
}

void __saveds __stdargs SVLI_ControlPads(ULONG *rtg)
{
 struct SV_ControlPad *pad;
 char *content; 

 *rtg = FALSE;

 if(SVSUP_LoadControlPad("ENV:superview-library/ECS.controlpad", &pad))
  {
   if(SVSUP_FindControlPadNoCase(pad, "BITMAPCOPY", &content)) if(content) if(!stricmp(content, "RTG")) *rtg = TRUE;

   SVSUP_FreeControlPad(pad);
  }
}

#include <proto/superview.h>

struct SVP_OperatorNode * __saveds __stdargs SVLI_GetOperator24(void)
{
 struct SV_ControlPad *pad;
 char *content; 
 APTR op = N;
 struct SuperViewBase *SuperViewBase;
 
 SuperViewBase = (APTR) OpenLibrary("superview.library", 9);
 if(SuperViewBase)
  {
   if(SVSUP_LoadControlPad("ENV:superview-library/ECS.controlpad", &pad))
    {
     if(SVSUP_FindControlPadNoCase(pad, "24BITOPERATOR", &content))
      {
       if(content)
        {
         char buf [256];

         strcpy(buf, content);

         if( stricmp(&buf[strlen(buf)-11], ".svoperator")) strcat(buf, ".svoperator");

         op = FindName(&SuperViewBase->svb_SVOperatorList, buf);
        }
      }

     SVSUP_FreeControlPad(pad);
    }

   CloseLibrary((APTR) SuperViewBase);
  }

 return(op);
}

ULONG __saveds __stdargs SVLI_Do24BitOperation(struct SVDriverHandle *SVDriverHandle, struct SV_GfxBuffer *source, struct SV_GfxBuffer **dest, struct SVP_OperatorNode *op)
{
 ULONG retval = SVERR_NO_ERROR;
 APTR handle2;
 struct SuperViewBase *SuperViewBase;

 *dest = N;
 
 SuperViewBase = (APTR) OpenLibrary("superview.library", 9);
 if(SuperViewBase)
  {
   handle2 = SVL_AllocHandle(N);
   if(handle2)
    {
     retval = SVL_DoOperation(handle2, source, dest, op, N);
    }else retval = SVERR_NO_HANDLE;

   CloseLibrary((APTR) SuperViewBase);

  }else retval = SVERR_VERSION_CONFLICT;

 SVDriverHandle->ah_OperatorHandle = handle2;

 return(retval);
}

void __saveds __stdargs SVLI_Free24BitOperator(struct SVDriverHandle *SVDriverHandle)
{
 struct SuperViewBase *SuperViewBase;

 SuperViewBase = (APTR) OpenLibrary("superview.library", 9);
 if(SuperViewBase)
  {
   if(SVDriverHandle)
    {
     if(SVDriverHandle->ah_OperatorHandle)
      {
       SVL_FreeHandle(SVDriverHandle->ah_OperatorHandle);
       SVDriverHandle->ah_OperatorHandle = N;
      }
    }
   CloseLibrary((APTR) SuperViewBase);
  }
}
