update for HEAD-2003050101
[reactos.git] / subsys / win32k / objects / dc.c
index 7727c29..d72b684 100644 (file)
@@ -19,8 +19,9 @@
 #include <win32k/pen.h>
 #include <win32k/text.h>
 #include "../eng/handle.h"
+#include <include/inteng.h>
 
-//#define NDEBUG
+#define NDEBUG
 #include <win32k/debug1.h>
 
 static GDIDEVICE PrimarySurface;
@@ -85,8 +86,6 @@ INT STDCALL  func_name( HDC hdc, INT mode ) \
 }
 
 
-VOID BitmapToSurf(HDC hdc, PSURFGDI SurfGDI, PSURFOBJ SurfObj, PBITMAPOBJ Bitmap);
-
 //  ---------------------------------------------------------  File Statics
 
 static void  W32kSetDCState16(HDC  hDC, HDC  hDCSave);
@@ -102,7 +101,6 @@ HDC STDCALL  W32kCreateCompatableDC(HDC  hDC)
 {
   PDC  NewDC, OrigDC = NULL;
   HBITMAP  hBitmap;
-  SIZEL onebyone;
   HDC hNewDC;
 
   OrigDC = DC_HandleToPtr(hDC);
@@ -139,11 +137,6 @@ HDC STDCALL  W32kCreateCompatableDC(HDC  hDC)
     NewDC->DevInfo = OrigDC->DevInfo;
   }
 
-  // Create a 1x1 monochrome bitmap surface
-  onebyone.cx = 1;
-  onebyone.cy = 1;
-  NewDC->Surface = EngCreateBitmap(onebyone, 1, BMF_1BPP, 0, NULL);
-
   /* DriverName is copied in the AllocDC routine  */
   if(OrigDC == NULL) {
     NewDC->DeviceDriver = DRIVER_FindMPDriver(NewDC->DriverName);
@@ -162,7 +155,7 @@ HDC STDCALL  W32kCreateCompatableDC(HDC  hDC)
   /* Create default bitmap */
   if (!(hBitmap = W32kCreateBitmap( 1, 1, 1, 1, NULL )))
   {
-       DC_ReleasePtr( hNewDC );
+    DC_ReleasePtr( hNewDC );
     DC_FreeDC( hNewDC );
     return NULL;
   }
@@ -170,6 +163,7 @@ HDC STDCALL  W32kCreateCompatableDC(HDC  hDC)
   NewDC->w.bitsPerPixel = 1;
   NewDC->w.hBitmap      = hBitmap;
   NewDC->w.hFirstBitmap = hBitmap;
+  NewDC->Surface = BitmapToSurf(BITMAPOBJ_HandleToPtr(hBitmap));
 
   if(OrigDC != NULL)
   {
@@ -184,13 +178,61 @@ HDC STDCALL  W32kCreateCompatableDC(HDC  hDC)
   return  hNewDC;
 }
 
+static BOOL STDCALL FindDriverFileNames(PUNICODE_STRING DriverFileNames)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+  UNICODE_STRING RegistryPath;
+  NTSTATUS Status;
+
+  RtlInitUnicodeString(&RegistryPath, NULL);
+  RtlZeroMemory(QueryTable, sizeof(QueryTable));
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[0].Name = L"\\Device\\Video0";
+  QueryTable[0].EntryContext = &RegistryPath;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
+                                  L"VIDEO",
+                                  QueryTable,
+                                  NULL,
+                                  NULL);
+  if (! NT_SUCCESS(Status))
+  {
+    DPRINT1("No \\Device\\Video0 value in DEVICEMAP\\VIDEO found\n");
+    return FALSE;
+  }
+
+  DPRINT("RegistryPath %S\n", RegistryPath.Buffer);
+
+  QueryTable[0].Name = L"InstalledDisplayDrivers";
+  QueryTable[0].EntryContext = DriverFileNames;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                  RegistryPath.Buffer,
+                                  QueryTable,
+                                  NULL,
+                                  NULL);
+  RtlFreeUnicodeString(&RegistryPath);
+  if (! NT_SUCCESS(Status))
+  {
+    DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
+    return FALSE;
+  }
+
+  DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
+
+  return TRUE;
+}
+
 BOOL STDCALL W32kCreatePrimarySurface(LPCWSTR Driver,
                                      LPCWSTR Device)
 {
-  PGD_ENABLEDRIVER  GDEnableDriver;
+  PGD_ENABLEDRIVER GDEnableDriver;
   HANDLE DeviceDriver;
-  DRVENABLEDATA  DED;
+  DRVENABLEDATA DED;
   PSURFOBJ SurfObj;
+  UNICODE_STRING DriverFileNames;
+  PWSTR CurrentName;
+  BOOL GotDriver;
 
   /*  Open the miniport driver  */
   if ((DeviceDriver = DRIVER_FindMPDriver(Driver)) == NULL)
@@ -199,22 +241,64 @@ BOOL STDCALL W32kCreatePrimarySurface(LPCWSTR Driver,
     return(FALSE);
   }
 
-  /*  Get the DDI driver's entry point  */
-  /*  FIXME: Retrieve DDI driver name from registry */
-  if ((GDEnableDriver = DRIVER_FindDDIDriver(L"\\SystemRoot\\system32\\drivers\\vgaddi.dll")) == NULL)
+  /*  Retrieve DDI driver names from registry */
+  RtlInitUnicodeString(&DriverFileNames, NULL);
+  if (! FindDriverFileNames(&DriverFileNames))
   {
-    DPRINT("FindDDIDriver failed\n");
+    DPRINT("FindDriverFileNames failed\n");
     return(FALSE);
   }
 
-  /*  Call DDI driver's EnableDriver function  */
-  RtlZeroMemory(&DED, sizeof(DED));
+  /* DriverFileNames may be a list of drivers in REG_SZ_MULTI format, scan all of
+     them until a good one found */
+  CurrentName = DriverFileNames.Buffer;
+  GotDriver = FALSE;
+  while (! GotDriver && CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
+  {
+    /*  Get the DDI driver's entry point  */
+    GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
+    if (NULL == GDEnableDriver)
+    {
+      DPRINT("FindDDIDriver failed for %S\n", CurrentName);
+    }
+    else
+    {
+      /*  Call DDI driver's EnableDriver function  */
+      RtlZeroMemory(&DED, sizeof(DED));
 
-  if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
+      if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
+      {
+        DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
+      }
+      else
+      {
+        GotDriver = TRUE;
+      }
+    }
+
+    if (! GotDriver)
+    {
+      /* Skip to the next name but never get past the Unicode string */
+      while (L'\0' != *CurrentName &&
+             CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
+      {
+       CurrentName++;
+      }
+      if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
+      {
+        CurrentName++;
+      }
+    }
+  }
+  RtlFreeUnicodeString(&DriverFileNames);
+  if (! GotDriver)
   {
-    DPRINT("DrvEnableDriver failed\n");
-    return(FALSE);
+    DPRINT("No suitable driver found\n");
+    return FALSE;
   }
+
+  DPRINT("Display driver %S loaded\n", DriverName);
+
   DPRINT("Building DDI Functions\n");
 
   /*  Construct DDI driver function dispatch table  */
@@ -267,8 +351,10 @@ BOOL STDCALL W32kCreatePrimarySurface(LPCWSTR Driver,
   PrimarySurface.Handle =
     PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
 
-  SurfObj = (PSURFOBJ)AccessUserObject(PrimarySurface.Handle);
+  SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
   SurfObj->dhpdev = PrimarySurface.PDev;
+
+  return TRUE;
 }
 
 HDC STDCALL  W32kCreateDC(LPCWSTR  Driver,
@@ -276,9 +362,10 @@ HDC STDCALL  W32kCreateDC(LPCWSTR  Driver,
                   LPCWSTR  Output,
                   CONST PDEVMODEW  InitData)
 {
-  HDC  hNewDC;
-  PDC  NewDC;
-  HDC  hDC = NULL;
+  HDC      hNewDC;
+  PDC      NewDC;
+  HDC      hDC = NULL;
+  PSURFGDI SurfGDI;
 
   /*  Check for existing DC object  */
   if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
@@ -323,19 +410,21 @@ HDC STDCALL  W32kCreateDC(LPCWSTR  Driver,
   /* FIXME: get mode selection information from somewhere  */
 
   NewDC->DMW.dmLogPixels = 96;
-  NewDC->DMW.dmBitsPerPel = 4;
-  NewDC->DMW.dmPelsWidth = 640;
-  NewDC->DMW.dmPelsHeight = 480;
+  SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
+  NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel;
+  NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx;
+  NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy;
   NewDC->DMW.dmDisplayFlags = 0;
   NewDC->DMW.dmDisplayFrequency = 0;
 
-  NewDC->w.bitsPerPixel = 4; // FIXME: set this here??
+  NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here??
 
   NewDC->w.hPalette = NewDC->DevInfo.hpalDefault;
 
   DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
 
-  NewDC->w.hVisRgn = W32kCreateRectRgn(0, 0, 640, 480);
+  NewDC->w.hVisRgn = W32kCreateRectRgn(0, 0, SurfGDI->SurfObj.sizlBitmap.cx,
+                                       SurfGDI->SurfObj.sizlBitmap.cy);
   DC_ReleasePtr( hNewDC );
 
   /*  Initialize the DC state  */
@@ -405,8 +494,10 @@ BOOL STDCALL W32kDeleteDC(HDC  DCHandle)
     W32kSelectObject (DCHandle, STOCK_WHITE_BRUSH);
     W32kSelectObject (DCHandle, STOCK_SYSTEM_FONT);
     DC_LockDC (DCHandle); W32kSelectObject does not recognize stock objects yet  */
+    BITMAPOBJ_ReleasePtr(DCToDelete->w.hBitmap);
     if (DCToDelete->w.flags & DC_MEMORY)
     {
+      EngDeleteSurface (DCToDelete->Surface);
       W32kDeleteObject (DCToDelete->w.hFirstBitmap);
     }
   }
@@ -929,15 +1020,14 @@ HGDIOBJ STDCALL W32kSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
 {
   HGDIOBJ   objOrg;
   BITMAPOBJ *pb;
-  PSURFOBJ  surfobj;
-  PSURFGDI  surfgdi;
   PDC dc;
   PPENOBJ pen;
   PBRUSHOBJ brush;
   PXLATEOBJ XlateObj;
   PPALGDI PalGDI;
   WORD  objectMagic;
-  ULONG NumColors;
+  COLORREF *ColorMap;
+  ULONG NumColors, Index;
 
   if(!hDC || !hGDIObj) return NULL;
 
@@ -953,49 +1043,52 @@ HGDIOBJ STDCALL W32kSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
       dc->w.hPen = hGDIObj;
 
       // Convert the color of the pen to the format of the DC
-      PalGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette);
-         if( PalGDI ){
-       XlateObj = (PXLATEOBJ)EngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
+      PalGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
+      if( PalGDI ){
+       XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
        pen = GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
-               if( pen ){
-               pen->logpen.lopnColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
-               }
-               GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
-         }
+       if( pen ){
+         pen->logpen.lopnColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
+       }
+       GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
+       EngDeleteXlate(XlateObj);
+      }
       break;
+
     case GO_BRUSH_MAGIC:
       objOrg = (HGDIOBJ)dc->w.hBrush;
       dc->w.hBrush = (HBRUSH) hGDIObj;
 
       // Convert the color of the brush to the format of the DC
-      PalGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette);
-         if( PalGDI ){
-       XlateObj = (PXLATEOBJ)EngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
+      PalGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
+      if( PalGDI ){
+       XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
        brush = GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
-               if( brush ){
-               brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
-               }
-               GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC);
-         }
+       if( brush ){
+         brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
+       }
+       GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC);
+       EngDeleteXlate(XlateObj);
+      }
       break;
-      case GO_FONT_MAGIC:
+
+    case GO_FONT_MAGIC:
       objOrg = (HGDIOBJ)dc->w.hFont;
       dc->w.hFont = (HFONT) hGDIObj;
+      TextIntRealizeFont(dc->w.hFont);
       break;
+
     case GO_BITMAP_MAGIC:
       // must be memory dc to select bitmap
       if (!(dc->w.flags & DC_MEMORY)) return NULL;
       objOrg = (HGDIOBJ)dc->w.hBitmap;
 
-      // setup mem dc for drawing into bitmap
-      pb   = BITMAPOBJ_HandleToPtr (hGDIObj);
-      dc->w.hBitmap = CreateGDIHandle(sizeof( SURFGDI ), sizeof( SURFOBJ )); // Assign the DC's bitmap
-
-      surfobj = (PSURFOBJ) AccessUserObject( dc->w.hBitmap );
-      surfgdi = (PSURFGDI) AccessInternalObject( dc->w.hBitmap );
-      BitmapToSurf(hDC, surfgdi, surfobj, pb); // Put the bitmap in a surface
-
-      dc->Surface = dc->w.hBitmap;
+      /* Release the old bitmap, lock the new one and convert it to a SURF */
+      EngDeleteSurface(dc->Surface);
+      BITMAPOBJ_ReleasePtr(objOrg);
+      dc->w.hBitmap = hGDIObj;
+      pb = BITMAPOBJ_HandleToPtr(hGDIObj);
+      dc->Surface = BitmapToSurf(pb);
 
       // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
       if(pb->dib)
@@ -1008,11 +1101,19 @@ HGDIOBJ STDCALL W32kSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
           if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
           if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
 
-          dc->w.hPalette = EngCreatePalette(PAL_INDEXED, NumColors, pb->ColorMap, 0, 0, 0);
+          ColorMap = ExAllocatePool(PagedPool, sizeof(COLORREF) * NumColors);
+          for (Index = 0; Index < NumColors; Index++)
+            {
+            ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
+                                  pb->ColorMap[Index].rgbGreen,
+                                  pb->ColorMap[Index].rgbBlue);
+          }
+          dc->w.hPalette = EngCreatePalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
+          ExFreePool(ColorMap);
         } else
-        if((pb->dib->dsBmih.biBitCount > 8) && (pb->dib->dsBmih.biBitCount < 24))
+        if(16 == pb->dib->dsBmih.biBitCount)
         {
-          dc->w.hPalette = EngCreatePalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
+          dc->w.hPalette = EngCreatePalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
         } else
         if(pb->dib->dsBmih.biBitCount >= 24)
         {
@@ -1022,6 +1123,7 @@ HGDIOBJ STDCALL W32kSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
         dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
       }
       break;
+
 #if UPDATEREGIONS
     case GO_REGION_MAGIC:
       /* objOrg = (HGDIOBJ)hDC->region; */
@@ -1225,7 +1327,7 @@ void  DC_InitDC(HDC  DCHandle)
 //  W32kRealizeDefaultPalette(DCHandle);
 
   W32kSelectObject(DCHandle, W32kGetStockObject( WHITE_BRUSH ));
-  //W32kSelectObject(DCHandle, hPen);
+  W32kSelectObject(DCHandle, W32kGetStockObject( BLACK_PEN ));
   //W32kSelectObject(DCHandle, hFont);
 
 //  CLIPPING_UpdateGCRegion(DCToInit);