Sync with trunk head
[reactos.git] / drivers / video / displays / framebuf_new / screen.c
1 /*
2 * PROJECT: ReactOS Framebuffer Display Driver
3 * LICENSE: Microsoft NT4 DDK Sample Code License
4 * FILE: boot/drivers/video/displays/framebuf/screen.c
5 * PURPOSE: Surface, Screen and PDEV support/initialization
6 * PROGRAMMERS: Copyright (c) 1992-1995 Microsoft Corporation
7 * ReactOS Portable Systems Group
8 */
9 #include "driver.h"
10
11 #define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_DONTCARE,L"System"}
12 #define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,VARIABLE_PITCH | FF_DONTCARE,L"MS Sans Serif"}
13 #define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,FIXED_PITCH | FF_DONTCARE, L"Courier"}
14
15 // This is the basic devinfo for a default driver. This is used as a base and customized based
16 // on information passed back from the miniport driver.
17
18 const DEVINFO gDevInfoFrameBuffer = {
19 ( GCAPS_OPAQUERECT
20 | GCAPS_MONO_DITHER
21 ), /* Graphics capabilities */
22 SYSTM_LOGFONT, /* Default font description */
23 HELVE_LOGFONT, /* ANSI variable font description */
24 COURI_LOGFONT, /* ANSI fixed font description */
25 0, /* Count of device fonts */
26 0, /* Preferred DIB format */
27 8, /* Width of color dither */
28 8, /* Height of color dither */
29 0 /* Default palette to use for this device */
30 };
31
32 /******************************Public*Routine******************************\
33 * bInitSURF
34 *
35 * Enables the surface. Maps the frame buffer into memory.
36 *
37 \**************************************************************************/
38
39 BOOL bInitSURF(PPDEV ppdev, BOOL bFirst)
40 {
41 DWORD returnedDataLength;
42 DWORD MaxWidth, MaxHeight;
43 VIDEO_MEMORY videoMemory;
44 VIDEO_MEMORY_INFORMATION videoMemoryInformation;
45 // eVb: 2.1 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
46 ULONG RemappingNeeded = 0;
47 // eVb: 2.1 [END]
48 //
49 // Set the current mode into the hardware.
50 //
51
52 if (EngDeviceIoControl(ppdev->hDriver,
53 IOCTL_VIDEO_SET_CURRENT_MODE,
54 &(ppdev->ulMode),
55 sizeof(ULONG),
56 // eVb: 2.2 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
57 &RemappingNeeded,
58 sizeof(ULONG),
59 // eVb: 2.2 [END]
60 &returnedDataLength))
61 {
62 RIP("DISP bInitSURF failed IOCTL_SET_MODE\n");
63 return(FALSE);
64 }
65
66 //
67 // If this is the first time we enable the surface we need to map in the
68 // memory also.
69 //
70 // eVb: 2.3 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
71 if (bFirst || RemappingNeeded)
72 {
73 // eVb: 2.3 [END]
74 videoMemory.RequestedVirtualAddress = NULL;
75
76 if (EngDeviceIoControl(ppdev->hDriver,
77 IOCTL_VIDEO_MAP_VIDEO_MEMORY,
78 &videoMemory,
79 sizeof(VIDEO_MEMORY),
80 &videoMemoryInformation,
81 sizeof(VIDEO_MEMORY_INFORMATION),
82 &returnedDataLength))
83 {
84 RIP("DISP bInitSURF failed IOCTL_VIDEO_MAP\n");
85 return(FALSE);
86 }
87
88 ppdev->pjScreen = (PBYTE)(videoMemoryInformation.FrameBufferBase);
89
90 if (videoMemoryInformation.FrameBufferBase !=
91 videoMemoryInformation.VideoRamBase)
92 {
93 RIP("VideoRamBase does not correspond to FrameBufferBase\n");
94 }
95 // eVb: 2.4 [DDK Change] - Make sure frame buffer mapping worked
96 //
97 // Make sure we can access this video memory
98 //
99
100 *(PULONG)(ppdev->pjScreen) = 0xaa55aa55;
101
102 if (*(PULONG)(ppdev->pjScreen) != 0xaa55aa55) {
103
104 DISPDBG((1, "Frame buffer memory is not accessible.\n"));
105 return(FALSE);
106 }
107 // eVb: 2.4 [END]
108 ppdev->cScreenSize = videoMemoryInformation.VideoRamLength;
109
110 //
111 // Initialize the head of the offscreen list to NULL.
112 //
113
114 ppdev->pOffscreenList = NULL;
115
116 // It's a hardware pointer; set up pointer attributes.
117
118 MaxHeight = ppdev->PointerCapabilities.MaxHeight;
119
120 // Allocate space for two DIBs (data/mask) for the pointer. If this
121 // device supports a color Pointer, we will allocate a larger bitmap.
122 // If this is a color bitmap we allocate for the largest possible
123 // bitmap because we have no idea of what the pixel depth might be.
124
125 // Width rounded up to nearest byte multiple
126
127 if (!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER))
128 {
129 MaxWidth = (ppdev->PointerCapabilities.MaxWidth + 7) / 8;
130 }
131 else
132 {
133 MaxWidth = ppdev->PointerCapabilities.MaxWidth * sizeof(DWORD);
134 }
135
136 ppdev->cjPointerAttributes =
137 sizeof(VIDEO_POINTER_ATTRIBUTES) +
138 ((sizeof(UCHAR) * MaxWidth * MaxHeight) * 2);
139
140 ppdev->pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES)
141 EngAllocMem(0, ppdev->cjPointerAttributes, ALLOC_TAG);
142
143 if (ppdev->pPointerAttributes == NULL) {
144
145 DISPDBG((0, "bInitPointer EngAllocMem failed\n"));
146 return(FALSE);
147 }
148
149 ppdev->pPointerAttributes->Flags = ppdev->PointerCapabilities.Flags;
150 ppdev->pPointerAttributes->WidthInBytes = MaxWidth;
151 ppdev->pPointerAttributes->Width = ppdev->PointerCapabilities.MaxWidth;
152 ppdev->pPointerAttributes->Height = MaxHeight;
153 ppdev->pPointerAttributes->Column = 0;
154 ppdev->pPointerAttributes->Row = 0;
155 ppdev->pPointerAttributes->Enable = 0;
156 }
157
158 return(TRUE);
159 }
160
161 /******************************Public*Routine******************************\
162 * vDisableSURF
163 *
164 * Disable the surface. Un-Maps the frame in memory.
165 *
166 \**************************************************************************/
167
168 VOID vDisableSURF(PPDEV ppdev)
169 {
170 DWORD returnedDataLength;
171 VIDEO_MEMORY videoMemory;
172
173 videoMemory.RequestedVirtualAddress = (PVOID) ppdev->pjScreen;
174
175 if (EngDeviceIoControl(ppdev->hDriver,
176 IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
177 &videoMemory,
178 sizeof(VIDEO_MEMORY),
179 NULL,
180 0,
181 &returnedDataLength))
182 {
183 RIP("DISP vDisableSURF failed IOCTL_VIDEO_UNMAP\n");
184 }
185 }
186
187
188 /******************************Public*Routine******************************\
189 * bInitPDEV
190 *
191 * Determine the mode we should be in based on the DEVMODE passed in.
192 * Query mini-port to get information needed to fill in the DevInfo and the
193 * GdiInfo .
194 *
195 \**************************************************************************/
196
197 BOOL bInitPDEV(
198 PPDEV ppdev,
199 DEVMODEW *pDevMode,
200 GDIINFO *pGdiInfo,
201 DEVINFO *pDevInfo)
202 {
203 ULONG cModes;
204 PVIDEO_MODE_INFORMATION pVideoBuffer, pVideoModeSelected, pVideoTemp;
205 VIDEO_COLOR_CAPABILITIES colorCapabilities;
206 ULONG ulTemp;
207 BOOL bSelectDefault;
208 ULONG cbModeSize;
209
210 //
211 // calls the miniport to get mode information.
212 //
213
214 cModes = getAvailableModes(ppdev->hDriver, &pVideoBuffer, &cbModeSize);
215
216 if (cModes == 0)
217 {
218 return(FALSE);
219 }
220
221 //
222 // Now see if the requested mode has a match in that table.
223 //
224
225 pVideoModeSelected = NULL;
226 pVideoTemp = pVideoBuffer;
227
228 if ((pDevMode->dmPelsWidth == 0) &&
229 (pDevMode->dmPelsHeight == 0) &&
230 (pDevMode->dmBitsPerPel == 0) &&
231 (pDevMode->dmDisplayFrequency == 0))
232 {
233 DISPDBG((2, "Default mode requested"));
234 bSelectDefault = TRUE;
235 }
236 else
237 {
238 // eVb: 2.5 [DDK Change] - Add missing newlines to debug output
239 DISPDBG((2, "Requested mode...\n"));
240 DISPDBG((2, " Screen width -- %li\n", pDevMode->dmPelsWidth));
241 DISPDBG((2, " Screen height -- %li\n", pDevMode->dmPelsHeight));
242 DISPDBG((2, " Bits per pel -- %li\n", pDevMode->dmBitsPerPel));
243 DISPDBG((2, " Frequency -- %li\n", pDevMode->dmDisplayFrequency));
244 // eVb: 2.5 [END]
245 bSelectDefault = FALSE;
246 }
247
248 while (cModes--)
249 {
250 if (pVideoTemp->Length != 0)
251 {
252 if (bSelectDefault ||
253 ((pVideoTemp->VisScreenWidth == pDevMode->dmPelsWidth) &&
254 (pVideoTemp->VisScreenHeight == pDevMode->dmPelsHeight) &&
255 (pVideoTemp->BitsPerPlane *
256 pVideoTemp->NumberOfPlanes == pDevMode->dmBitsPerPel) &&
257 (pVideoTemp->Frequency == pDevMode->dmDisplayFrequency)))
258 {
259 pVideoModeSelected = pVideoTemp;
260 DISPDBG((3, "Found a match\n")) ;
261 break;
262 }
263 }
264
265 pVideoTemp = (PVIDEO_MODE_INFORMATION)
266 (((PUCHAR)pVideoTemp) + cbModeSize);
267 }
268
269 //
270 // If no mode has been found, return an error
271 //
272
273 if (pVideoModeSelected == NULL)
274 {
275 EngFreeMem(pVideoBuffer);
276 DISPDBG((0,"DISP bInitPDEV failed - no valid modes\n"));
277 return(FALSE);
278 }
279
280 //
281 // Fill in the GDIINFO data structure with the information returned from
282 // the kernel driver.
283 //
284
285 ppdev->ulMode = pVideoModeSelected->ModeIndex;
286 ppdev->cxScreen = pVideoModeSelected->VisScreenWidth;
287 ppdev->cyScreen = pVideoModeSelected->VisScreenHeight;
288 ppdev->ulBitCount = pVideoModeSelected->BitsPerPlane *
289 pVideoModeSelected->NumberOfPlanes;
290 ppdev->lDeltaScreen = pVideoModeSelected->ScreenStride;
291
292 ppdev->flRed = pVideoModeSelected->RedMask;
293 ppdev->flGreen = pVideoModeSelected->GreenMask;
294 ppdev->flBlue = pVideoModeSelected->BlueMask;
295
296
297 pGdiInfo->ulVersion = GDI_DRIVER_VERSION;
298 pGdiInfo->ulTechnology = DT_RASDISPLAY;
299 pGdiInfo->ulHorzSize = pVideoModeSelected->XMillimeter;
300 pGdiInfo->ulVertSize = pVideoModeSelected->YMillimeter;
301
302 pGdiInfo->ulHorzRes = ppdev->cxScreen;
303 pGdiInfo->ulVertRes = ppdev->cyScreen;
304 pGdiInfo->ulPanningHorzRes = ppdev->cxScreen;
305 pGdiInfo->ulPanningVertRes = ppdev->cyScreen;
306 pGdiInfo->cBitsPixel = pVideoModeSelected->BitsPerPlane;
307 pGdiInfo->cPlanes = pVideoModeSelected->NumberOfPlanes;
308 pGdiInfo->ulVRefresh = pVideoModeSelected->Frequency;
309 pGdiInfo->ulBltAlignment = 1; // We don't have accelerated screen-
310 // to-screen blts, and any
311 // window alignment is okay
312
313 pGdiInfo->ulLogPixelsX = pDevMode->dmLogPixels;
314 pGdiInfo->ulLogPixelsY = pDevMode->dmLogPixels;
315
316 #ifdef MIPS
317 if (ppdev->ulBitCount == 8)
318 pGdiInfo->flTextCaps = (TC_RA_ABLE | TC_SCROLLBLT);
319 else
320 #endif
321 pGdiInfo->flTextCaps = TC_RA_ABLE;
322
323 pGdiInfo->flRaster = 0; // flRaster is reserved by DDI
324
325 pGdiInfo->ulDACRed = pVideoModeSelected->NumberRedBits;
326 pGdiInfo->ulDACGreen = pVideoModeSelected->NumberGreenBits;
327 pGdiInfo->ulDACBlue = pVideoModeSelected->NumberBlueBits;
328
329 pGdiInfo->ulAspectX = 0x24; // One-to-one aspect ratio
330 pGdiInfo->ulAspectY = 0x24;
331 pGdiInfo->ulAspectXY = 0x33;
332
333 pGdiInfo->xStyleStep = 1; // A style unit is 3 pels
334 pGdiInfo->yStyleStep = 1;
335 pGdiInfo->denStyleStep = 3;
336
337 pGdiInfo->ptlPhysOffset.x = 0;
338 pGdiInfo->ptlPhysOffset.y = 0;
339 pGdiInfo->szlPhysSize.cx = 0;
340 pGdiInfo->szlPhysSize.cy = 0;
341
342 // RGB and CMY color info.
343
344 //
345 // try to get it from the miniport.
346 // if the miniport doesn ot support this feature, use defaults.
347 //
348
349 if (EngDeviceIoControl(ppdev->hDriver,
350 IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES,
351 NULL,
352 0,
353 &colorCapabilities,
354 sizeof(VIDEO_COLOR_CAPABILITIES),
355 &ulTemp))
356 {
357
358 DISPDBG((2, "getcolorCapabilities failed \n"));
359
360 pGdiInfo->ciDevice.Red.x = 6700;
361 pGdiInfo->ciDevice.Red.y = 3300;
362 pGdiInfo->ciDevice.Red.Y = 0;
363 pGdiInfo->ciDevice.Green.x = 2100;
364 pGdiInfo->ciDevice.Green.y = 7100;
365 pGdiInfo->ciDevice.Green.Y = 0;
366 pGdiInfo->ciDevice.Blue.x = 1400;
367 pGdiInfo->ciDevice.Blue.y = 800;
368 pGdiInfo->ciDevice.Blue.Y = 0;
369 pGdiInfo->ciDevice.AlignmentWhite.x = 3127;
370 pGdiInfo->ciDevice.AlignmentWhite.y = 3290;
371 pGdiInfo->ciDevice.AlignmentWhite.Y = 0;
372
373 pGdiInfo->ciDevice.RedGamma = 20000;
374 pGdiInfo->ciDevice.GreenGamma = 20000;
375 pGdiInfo->ciDevice.BlueGamma = 20000;
376
377 }
378 else
379 {
380 pGdiInfo->ciDevice.Red.x = colorCapabilities.RedChromaticity_x;
381 pGdiInfo->ciDevice.Red.y = colorCapabilities.RedChromaticity_y;
382 pGdiInfo->ciDevice.Red.Y = 0;
383 pGdiInfo->ciDevice.Green.x = colorCapabilities.GreenChromaticity_x;
384 pGdiInfo->ciDevice.Green.y = colorCapabilities.GreenChromaticity_y;
385 pGdiInfo->ciDevice.Green.Y = 0;
386 pGdiInfo->ciDevice.Blue.x = colorCapabilities.BlueChromaticity_x;
387 pGdiInfo->ciDevice.Blue.y = colorCapabilities.BlueChromaticity_y;
388 pGdiInfo->ciDevice.Blue.Y = 0;
389 pGdiInfo->ciDevice.AlignmentWhite.x = colorCapabilities.WhiteChromaticity_x;
390 pGdiInfo->ciDevice.AlignmentWhite.y = colorCapabilities.WhiteChromaticity_y;
391 pGdiInfo->ciDevice.AlignmentWhite.Y = colorCapabilities.WhiteChromaticity_Y;
392
393 // if we have a color device store the three color gamma values,
394 // otherwise store the unique gamma value in all three.
395
396 if (colorCapabilities.AttributeFlags & VIDEO_DEVICE_COLOR)
397 {
398 pGdiInfo->ciDevice.RedGamma = colorCapabilities.RedGamma;
399 pGdiInfo->ciDevice.GreenGamma = colorCapabilities.GreenGamma;
400 pGdiInfo->ciDevice.BlueGamma = colorCapabilities.BlueGamma;
401 }
402 else
403 {
404 pGdiInfo->ciDevice.RedGamma = colorCapabilities.WhiteGamma;
405 pGdiInfo->ciDevice.GreenGamma = colorCapabilities.WhiteGamma;
406 pGdiInfo->ciDevice.BlueGamma = colorCapabilities.WhiteGamma;
407 }
408
409 };
410
411 pGdiInfo->ciDevice.Cyan.x = 0;
412 pGdiInfo->ciDevice.Cyan.y = 0;
413 pGdiInfo->ciDevice.Cyan.Y = 0;
414 pGdiInfo->ciDevice.Magenta.x = 0;
415 pGdiInfo->ciDevice.Magenta.y = 0;
416 pGdiInfo->ciDevice.Magenta.Y = 0;
417 pGdiInfo->ciDevice.Yellow.x = 0;
418 pGdiInfo->ciDevice.Yellow.y = 0;
419 pGdiInfo->ciDevice.Yellow.Y = 0;
420
421 // No dye correction for raster displays.
422
423 pGdiInfo->ciDevice.MagentaInCyanDye = 0;
424 pGdiInfo->ciDevice.YellowInCyanDye = 0;
425 pGdiInfo->ciDevice.CyanInMagentaDye = 0;
426 pGdiInfo->ciDevice.YellowInMagentaDye = 0;
427 pGdiInfo->ciDevice.CyanInYellowDye = 0;
428 pGdiInfo->ciDevice.MagentaInYellowDye = 0;
429
430 pGdiInfo->ulDevicePelsDPI = 0; // For printers only
431 pGdiInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA;
432
433 // BUGBUG this should be modified to take into account the size
434 // of the display and the resolution.
435
436 pGdiInfo->ulHTPatternSize = HT_PATSIZE_4x4_M;
437
438 pGdiInfo->flHTFlags = HT_FLAG_ADDITIVE_PRIMS;
439
440 // Fill in the basic devinfo structure
441
442 *pDevInfo = gDevInfoFrameBuffer;
443
444 // Fill in the rest of the devinfo and GdiInfo structures.
445
446 if (ppdev->ulBitCount == 8)
447 {
448 // It is Palette Managed.
449
450 pGdiInfo->ulNumColors = 20;
451 pGdiInfo->ulNumPalReg = 1 << ppdev->ulBitCount;
452
453 pDevInfo->flGraphicsCaps |= (GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
454
455 pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP;
456 pDevInfo->iDitherFormat = BMF_8BPP;
457
458 // Assuming palette is orthogonal - all colors are same size.
459
460 ppdev->cPaletteShift = 8 - pGdiInfo->ulDACRed;
461 }
462 else
463 {
464 pGdiInfo->ulNumColors = (ULONG) (-1);
465 pGdiInfo->ulNumPalReg = 0;
466
467 if (ppdev->ulBitCount == 16)
468 {
469 pGdiInfo->ulHTOutputFormat = HT_FORMAT_16BPP;
470 pDevInfo->iDitherFormat = BMF_16BPP;
471 }
472 else if (ppdev->ulBitCount == 24)
473 {
474 pGdiInfo->ulHTOutputFormat = HT_FORMAT_24BPP;
475 pDevInfo->iDitherFormat = BMF_24BPP;
476 }
477 else
478 {
479 pGdiInfo->ulHTOutputFormat = HT_FORMAT_32BPP;
480 pDevInfo->iDitherFormat = BMF_32BPP;
481 }
482 }
483
484 EngFreeMem(pVideoBuffer);
485
486 return(TRUE);
487 }
488
489
490 /******************************Public*Routine******************************\
491 * getAvailableModes
492 *
493 * Calls the miniport to get the list of modes supported by the kernel driver,
494 * and returns the list of modes supported by the diplay driver among those
495 *
496 * returns the number of entries in the videomode buffer.
497 * 0 means no modes are supported by the miniport or that an error occured.
498 *
499 * NOTE: the buffer must be freed up by the caller.
500 *
501 \**************************************************************************/
502
503 DWORD getAvailableModes(
504 HANDLE hDriver,
505 PVIDEO_MODE_INFORMATION *modeInformation,
506 DWORD *cbModeSize)
507 {
508 ULONG ulTemp;
509 VIDEO_NUM_MODES modes;
510 PVIDEO_MODE_INFORMATION pVideoTemp;
511
512 //
513 // Get the number of modes supported by the mini-port
514 //
515
516 if (EngDeviceIoControl(hDriver,
517 IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES,
518 NULL,
519 0,
520 &modes,
521 sizeof(VIDEO_NUM_MODES),
522 &ulTemp))
523 {
524 DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_NUM_AVAIL_MODES\n"));
525 return(0);
526 }
527
528 *cbModeSize = modes.ModeInformationLength;
529
530 //
531 // Allocate the buffer for the mini-port to write the modes in.
532 //
533
534 *modeInformation = (PVIDEO_MODE_INFORMATION)
535 EngAllocMem(0, modes.NumModes *
536 modes.ModeInformationLength, ALLOC_TAG);
537
538 if (*modeInformation == (PVIDEO_MODE_INFORMATION) NULL)
539 {
540 DISPDBG((0, "getAvailableModes failed EngAllocMem\n"));
541
542 return 0;
543 }
544
545 //
546 // Ask the mini-port to fill in the available modes.
547 //
548
549 if (EngDeviceIoControl(hDriver,
550 IOCTL_VIDEO_QUERY_AVAIL_MODES,
551 NULL,
552 0,
553 *modeInformation,
554 modes.NumModes * modes.ModeInformationLength,
555 &ulTemp))
556 {
557
558 DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_AVAIL_MODES\n"));
559
560 EngFreeMem(*modeInformation);
561 *modeInformation = (PVIDEO_MODE_INFORMATION) NULL;
562
563 return(0);
564 }
565
566 //
567 // Now see which of these modes are supported by the display driver.
568 // As an internal mechanism, set the length to 0 for the modes we
569 // DO NOT support.
570 //
571
572 ulTemp = modes.NumModes;
573 pVideoTemp = *modeInformation;
574
575 //
576 // Mode is rejected if it is not one plane, or not graphics, or is not
577 // one of 8, 16 or 32 bits per pel.
578 //
579
580 while (ulTemp--)
581 {
582 if ((pVideoTemp->NumberOfPlanes != 1 ) ||
583 !(pVideoTemp->AttributeFlags & VIDEO_MODE_GRAPHICS) ||
584 // eVb: 2.6 [DDK CHANGE] - Do not process banked video modes
585 (pVideoTemp->AttributeFlags & VIDEO_MODE_BANKED) ||
586 // eVb: 2.6 [END]
587 ((pVideoTemp->BitsPerPlane != 8) &&
588 (pVideoTemp->BitsPerPlane != 16) &&
589 (pVideoTemp->BitsPerPlane != 24) &&
590 (pVideoTemp->BitsPerPlane != 32)))
591 {
592 pVideoTemp->Length = 0;
593 }
594
595 pVideoTemp = (PVIDEO_MODE_INFORMATION)
596 (((PUCHAR)pVideoTemp) + modes.ModeInformationLength);
597 }
598
599 return modes.NumModes;
600
601 }