Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1075 lines
33 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998-2000 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Internal "scan class" prototypes. These classes represent a set of
  8. * "primitive" operations, which are characterized by being quick to render,
  9. * and fairly simple to represent.
  10. *
  11. * [agodfrey] At time of writing, they are all scan-line operations, so the
  12. * name "scan class" kinda fits; however, we may need to add ones which
  13. * aren't scan-line oriented - e.g. one for aliased single-pixel-wide
  14. * opaque solid-filled lines.
  15. *
  16. * Revision History:
  17. *
  18. * 12/01/1998 andrewgo
  19. * Created it.
  20. * 02/22/2000 agodfrey
  21. * For ClearType, but also useful for other future improvements:
  22. * Expanded it to allow different types of record.
  23. * Cleared up some of the CachedBitmap confusion,
  24. * and removed the confusion between "opaque" and "SourceCopy".
  25. *
  26. \**************************************************************************/
  27. #ifndef _SCAN_HPP
  28. #define _SCAN_HPP
  29. #include <dciman.h>
  30. #include "alphablender.hpp"
  31. struct EpScanRecord;
  32. // This color is used as a default to detect bugs.
  33. const ARGB HorridInfraPurpleColor = 0x80ff80ff;
  34. // blenderNum:
  35. // Used when an operation mixes different scan types.
  36. // We don't use an enum because the meaning of each blender depends
  37. // on the situation.
  38. //
  39. // At the time of writing, only CachedBitmap uses this - to select
  40. // between the regular and opaque scan types.
  41. // BlenderMax: The number of different scan types allowed in one
  42. // Start() ... End() sequence. e.g. if this is 2, blenderNum can be 0 or 1.
  43. typedef VOID *(EpScan::* NEXTBUFFERFUNCTION)(
  44. INT x,
  45. INT y,
  46. INT newWidth,
  47. INT updateWidth,
  48. INT blenderNum
  49. );
  50. const INT BlenderMax = 2;
  51. //--------------------------------------------------------------------------
  52. // Scan iterator class
  53. //
  54. // [agodfrey]: The naming is confusing. Suggestions:
  55. // Rename "EpScan*" to "EpScanIterator".
  56. // Rename "NEXTBUFFERFUNCTION"
  57. // to something about "next scan", not "next buffer".
  58. // Make a stronger name distinction between EpScanIterator* and
  59. // EpScanBufferNative.
  60. //
  61. // NOTE: These classes are not reentrant, and therefore cannot be used
  62. // by more than one thread at a time. In actual use, this means
  63. // that their use must be synchronized under the device lock.
  64. //--------------------------------------------------------------------------
  65. class EpScan
  66. {
  67. public:
  68. // Some scan types have settings which are constant for an entire
  69. // Start() ... End() operation. Right now, there are only a few such
  70. // settings. So, we just pass them as parameters with defaults.
  71. //
  72. // But if this grows, we might need to put them in a structure,
  73. // or pass them in a separate call.
  74. //
  75. // pixFmtGeneral - the input pixel format for the color data,
  76. // in the "Blend" and "CT" scan types.
  77. // pixFmtOpaque - the input pixel format for the color data,
  78. // in the "Opaque" scan type.
  79. // solidColor - the solid fill color for "*SolidFill" scan types.
  80. // The default is chosen to detect bugs.
  81. virtual BOOL Start(
  82. DpDriver *driver,
  83. DpContext *context,
  84. DpBitmap *surface,
  85. NEXTBUFFERFUNCTION *getBuffer,
  86. EpScanType scanType,
  87. PixelFormatID pixFmtGeneral = PixelFormat32bppPARGB,
  88. PixelFormatID pixFmtOpaque = PixelFormat32bppPARGB,
  89. ARGB solidColor = HorridInfraPurpleColor
  90. )
  91. {
  92. // Common initialization stuff.
  93. BlenderConfig[0].ScanType = scanType;
  94. BlenderConfig[0].SourcePixelFormat = pixFmtGeneral;
  95. // For now, blender 1 is only used for CachedBitmap rendering;
  96. // it's the blender for the opaque, "native format" data.
  97. BlenderConfig[1].ScanType = EpScanTypeOpaque;
  98. BlenderConfig[1].SourcePixelFormat = pixFmtOpaque;
  99. CurrentX = 0;
  100. CurrentY = 0;
  101. DitherOriginX = context->RenderingOriginX;
  102. DitherOriginY = context->RenderingOriginY;
  103. return TRUE;
  104. }
  105. virtual VOID End(INT currentWidth) = 0;
  106. virtual VOID *GetCurrentBuffer() = 0;
  107. virtual BYTE *GetCurrentCTBuffer() = 0;
  108. virtual VOID Flush() = 0;
  109. // This function processes an entire batch of scans -
  110. // it handles multiple pixel formats and combinations
  111. // of Blend and Opaque
  112. // If a scan class doesn't support it, it returns FALSE.
  113. virtual BOOL ProcessBatch(
  114. EpScanRecord *batchStart,
  115. EpScanRecord *batchEnd,
  116. INT minX,
  117. INT minY,
  118. INT maxX,
  119. INT maxY
  120. )
  121. {
  122. return FALSE;
  123. }
  124. // The x and y coordinates for the current scanline (blending scanline).
  125. // not the current requested next buffer.
  126. INT CurrentX;
  127. INT CurrentY;
  128. // The origin for the dither pattern.
  129. INT DitherOriginX;
  130. INT DitherOriginY;
  131. // "Blender configuration"
  132. //
  133. // For one Start() ... End() sequence, at most two different scan types are
  134. // used, and often there's just one.
  135. // So, we allocate two EpAlphaBlender objects, and set them up
  136. // appropriately during Start().
  137. //
  138. // Right now, the second one is only used for CachedBitmap. But in the
  139. // future, it might be used e.g. to mix "solidfill" scans with
  140. // "blend" scans for antialiased solid fills. In that case, Start() will
  141. // need more parameters to tell it how to set up the blender objects.
  142. //
  143. // Note:
  144. //
  145. // In V2, we may want to avoid reinitializing the AlphaBlenders
  146. // for every primitive. But that'll take some work - there are many reasons
  147. // we might need to reinitialize. It wouldn't be enough to have
  148. // an EpAlphaBlender for each scan type (and I wouldn't recommend it
  149. // anyway.)
  150. // !!! [agodfrey] "EpBlenderConfig" and "BlenderConfig" could do with
  151. // better names. But I can't think of any.
  152. struct EpBlenderConfig
  153. {
  154. EpAlphaBlender AlphaBlender;
  155. PixelFormatID SourcePixelFormat;
  156. EpScanType ScanType;
  157. VOID Initialize(
  158. PixelFormatID dstFormat,
  159. const DpContext *context,
  160. const ColorPalette *dstpal,
  161. VOID **tempBuffers,
  162. BOOL dither16bpp,
  163. BOOL useRMW,
  164. ARGB solidColor)
  165. {
  166. AlphaBlender.Initialize(
  167. ScanType,
  168. dstFormat,
  169. SourcePixelFormat,
  170. context,
  171. dstpal,
  172. tempBuffers,
  173. dither16bpp,
  174. useRMW,
  175. solidColor);
  176. }
  177. };
  178. EpBlenderConfig BlenderConfig[BlenderMax];
  179. // LastBlenderNum:
  180. // Used by the flush mechanism in the NextBuffer functions
  181. // to figure out which AlphaBlender to use to flush the buffer.
  182. INT LastBlenderNum;
  183. };
  184. //--------------------------------------------------------------------------
  185. // Scan buffer class
  186. //
  187. // This class is intended to be used be any drawing code wishing to output
  188. // to a scan buffer; callers should not use the EpScan class directly.
  189. //--------------------------------------------------------------------------
  190. template<class T>
  191. class EpScanBufferNative
  192. {
  193. private:
  194. // We now use an ObjectTag to determine if the object is valid
  195. // instead of using a BOOL. This is much more robust and helps
  196. // with debugging. It also enables us to version our objects
  197. // more easily with a version number in the ObjectTag.
  198. ObjectTag Tag; // Keep this as the 1st value in the object!
  199. VOID SetValid(BOOL valid)
  200. {
  201. Tag = valid ? ObjectTagScanBufferNative : ObjectTagInvalid;
  202. }
  203. private:
  204. DpBitmap *Surface;
  205. EpScan *Scan;
  206. NEXTBUFFERFUNCTION NextBufferFunction;
  207. INT CurrentWidth;
  208. public:
  209. // noTransparentPixels - TRUE if there will be no transparent pixels.
  210. // If you're not sure, set it to FALSE.
  211. //
  212. // If it's set to TRUE, we'll substitute "Opaque" scan types for "Blend"
  213. // scan types - if the pixels are all opaque, they're equivalent,
  214. // and "Opaque" is faster.
  215. // solidColor - The solid color for *SolidFill scan types.
  216. // The default is chosen to detect bugs.
  217. EpScanBufferNative(
  218. EpScan *scan,
  219. DpDriver *driver,
  220. DpContext *context,
  221. DpBitmap *surface,
  222. BOOL noTransparentPixels = FALSE,
  223. EpScanType scanType = EpScanTypeBlend,
  224. PixelFormatID pixFmtGeneral = PixelFormat32bppPARGB,
  225. PixelFormatID pixFmtOpaque = PixelFormat32bppPARGB,
  226. ARGB solidColor = HorridInfraPurpleColor
  227. )
  228. {
  229. if ( noTransparentPixels
  230. && (scanType == EpScanTypeBlend))
  231. {
  232. scanType = EpScanTypeOpaque;
  233. }
  234. CurrentWidth = 0;
  235. Surface = surface;
  236. Scan = scan;
  237. SetValid(Scan->Start(
  238. driver,
  239. context,
  240. surface,
  241. &NextBufferFunction,
  242. scanType,
  243. pixFmtGeneral,
  244. pixFmtOpaque,
  245. solidColor
  246. ));
  247. }
  248. ~EpScanBufferNative()
  249. {
  250. if (IsValid())
  251. {
  252. Scan->End(CurrentWidth);
  253. }
  254. SetValid(FALSE); // so we don't use a deleted object
  255. }
  256. // This function processes an entire batch of scans -
  257. // it handles multiple pixel formats and combinations
  258. // of SourceOver and SourceCopy.
  259. // If it's unsupported, it returns FALSE.
  260. BOOL ProcessBatch(
  261. EpScanRecord *batchStart,
  262. EpScanRecord *batchEnd,
  263. INT minX,
  264. INT minY,
  265. INT maxX,
  266. INT maxY
  267. )
  268. {
  269. return Scan->ProcessBatch(batchStart, batchEnd, minX, minY, maxX, maxY);
  270. }
  271. BOOL IsValid() const
  272. {
  273. ASSERT((Tag == ObjectTagScanBufferNative) || (Tag == ObjectTagInvalid));
  274. #if DBG
  275. if (Tag == ObjectTagInvalid)
  276. {
  277. WARNING1("Invalid ScanBufferNative");
  278. }
  279. #endif
  280. return (Tag == ObjectTagScanBufferNative);
  281. }
  282. // NextBuffer() flushes the previous scan (if there was one) and
  283. // returns a pointer to the new buffer. Note that NextBuffer()
  284. // will never fail (but the constructor to EpScanBufferNative might
  285. // have!).
  286. //
  287. // blenderNum:
  288. // Used when an operation mixes different scan types.
  289. // We don't use an enum because the meaning of each blender depends
  290. // on the situation.
  291. //
  292. // At the time of writing, only CachedBitmap uses this - to select
  293. // between the regular and opaque scan types.
  294. //
  295. // Note: The contents of the buffer are not zeroed by NextBuffer().
  296. // Use NextBufferClear() if you want the contents zeroed if
  297. // you're doing an accumulation type of operation.
  298. //
  299. // Note: NextBuffer() may or may not return the same pointer as the
  300. // previous NextBuffer() call.
  301. T *NextBuffer(
  302. INT x, INT y,
  303. INT nextWidth,
  304. INT blenderNum = 0
  305. )
  306. {
  307. ASSERT(IsValid());
  308. T *buffer = (T *)((Scan->*NextBufferFunction)(
  309. x,
  310. y,
  311. nextWidth,
  312. CurrentWidth,
  313. blenderNum
  314. ));
  315. CurrentWidth = nextWidth;
  316. return buffer;
  317. }
  318. T *NextBufferClear(
  319. INT x, INT y,
  320. INT width,
  321. INT blenderNum = 0
  322. )
  323. {
  324. T *buffer = NextBuffer(x, y, width, blenderNum);
  325. GpMemset(buffer, 0, width * sizeof(T));
  326. return buffer;
  327. }
  328. // !!! [agodfrey]: It would be better to remove the CurrentWidth member,
  329. // and have UpdateWidth call a member in the Scan object.
  330. //
  331. // It would also make this class' NextBuffer implementation less
  332. // confusing - it wouldn't mix parameters describing the next scan
  333. // with parameters describing the current one.
  334. VOID UpdateWidth(INT width)
  335. {
  336. // The width can only be shrunk:
  337. ASSERT(width <= CurrentWidth);
  338. CurrentWidth = width;
  339. }
  340. DpBitmap *GetSurface()
  341. {
  342. return Surface;
  343. }
  344. T *GetCurrentBuffer()
  345. {
  346. return (T *)(Scan->GetCurrentBuffer());
  347. }
  348. BYTE *GetCurrentCTBuffer()
  349. {
  350. return Scan->GetCurrentCTBuffer();
  351. }
  352. };
  353. class EpPaletteMap;
  354. //--------------------------------------------------------------------------
  355. // Direct access to the bits
  356. //--------------------------------------------------------------------------
  357. // [agodfrey] EpScanEngine and EpScanBitmap have some common code. Consider
  358. // merging that code into a single class, derived from EpScan, and then
  359. // deriving EpScanEngine and EpScanBitmap from it.
  360. class EpScanEngine : public EpScan
  361. {
  362. private:
  363. BYTE *Dst;
  364. BYTE *Bits;
  365. INT Stride;
  366. INT PixelSize; // Presumably the pixel size of the destination.
  367. DpBitmap * Surface;
  368. VOID *Buffers[5];
  369. private:
  370. VOID *NextBuffer(
  371. INT x, INT y,
  372. INT newWidth,
  373. INT updateWidth,
  374. INT blenderNum
  375. );
  376. public:
  377. EpScanEngine() {}
  378. ~EpScanEngine() {}
  379. virtual BOOL Start(
  380. DpDriver *driver,
  381. DpContext *context,
  382. DpBitmap *surface,
  383. NEXTBUFFERFUNCTION *getBuffer,
  384. EpScanType scanType,
  385. PixelFormatID pixFmtGeneral,
  386. PixelFormatID pixFmtOpaque ,
  387. ARGB solidColor
  388. );
  389. virtual VOID End(INT updateWidth);
  390. virtual VOID* GetCurrentBuffer() { return static_cast<VOID *>(Buffers[3]); }
  391. virtual BYTE* GetCurrentCTBuffer()
  392. {
  393. ASSERT( (BlenderConfig[0].ScanType == EpScanTypeCT)
  394. || (BlenderConfig[0].ScanType == EpScanTypeCTSolidFill));
  395. return static_cast<BYTE *>(Buffers[4]);
  396. }
  397. virtual VOID Flush() {}
  398. };
  399. //--------------------------------------------------------------------------
  400. // Access to the GpBitmap bits
  401. //
  402. // This scan interface is used for scan drawing to a GpBitmap object.
  403. // The GpBitmap object is the internal representation of a GDI+ bitmap.
  404. //--------------------------------------------------------------------------
  405. class EpScanBitmap;
  406. typedef VOID (EpScanBitmap::*SCANENDFUNCTION)(INT updateWidth);
  407. class EpScanBitmap : public EpScan
  408. {
  409. private:
  410. DpBitmap* Surface;
  411. GpBitmap* Bitmap;
  412. INT Width;
  413. INT Height;
  414. BOOL BitmapLocked;
  415. BitmapData LockedBitmapData;
  416. UINT BitmapLockFlags;
  417. VOID* CurrentScan; // only used by NextBufferNative
  418. INT PixelSize; // only used by NextBufferNative
  419. VOID *Buffers[5];
  420. SCANENDFUNCTION EndFunc;
  421. private:
  422. VOID *NextBuffer32ARGB(
  423. INT x, INT y,
  424. INT newWidth,
  425. INT updateWidth,
  426. INT blenderNum
  427. );
  428. VOID *NextBufferNative(
  429. INT x, INT y,
  430. INT newWidth,
  431. INT updateWidth,
  432. INT blenderNum
  433. );
  434. VOID End32ARGB(INT updateWidth);
  435. VOID EndNative(INT updateWidth);
  436. public:
  437. EpScanBitmap()
  438. {
  439. Buffers[0] = NULL;
  440. BitmapLocked = FALSE;
  441. Bitmap = NULL;
  442. }
  443. ~EpScanBitmap() { FreeData(); }
  444. VOID SetBitmap(GpBitmap* bitmap)
  445. {
  446. Bitmap = bitmap;
  447. }
  448. VOID FreeData()
  449. {
  450. if (Buffers[0])
  451. GpFree(Buffers[0]);
  452. Buffers[0] = NULL;
  453. }
  454. virtual BOOL Start(
  455. DpDriver *driver,
  456. DpContext *context,
  457. DpBitmap *surface,
  458. NEXTBUFFERFUNCTION *getBuffer,
  459. EpScanType scanType,
  460. PixelFormatID pixFmtGeneral,
  461. PixelFormatID pixFmtOpaque,
  462. ARGB solidColor
  463. );
  464. virtual VOID End(INT updateWidth);
  465. virtual VOID *GetCurrentBuffer()
  466. {
  467. return static_cast<ARGB *>(Buffers[3]);
  468. }
  469. virtual BYTE* GetCurrentCTBuffer()
  470. {
  471. ASSERT( (BlenderConfig[0].ScanType == EpScanTypeCT)
  472. || (BlenderConfig[0].ScanType == EpScanTypeCTSolidFill));
  473. return static_cast<BYTE *>(Buffers[4]);
  474. }
  475. virtual VOID Flush();
  476. GpBitmap *GetBitmap()
  477. {
  478. return Bitmap;
  479. }
  480. };
  481. //--------------------------------------------------------------------------
  482. // Use either GDI or DCI for all scan drawing
  483. //--------------------------------------------------------------------------
  484. // MAKE_*WORD_ALIGNED:
  485. // Increments the pointer, if necessary, to the next aligned address.
  486. //
  487. // WARNING: If you use this, you need to remember the original pointer,
  488. // so that you can free the memory later.
  489. //
  490. // "p = MAKE_QWORD_ALIGNED(blah, p)" is a bug.
  491. #define MAKE_QWORD_ALIGNED(type, p) (\
  492. reinterpret_cast<type>((reinterpret_cast<INT_PTR>(p) + 7) & ~7))
  493. #define MAKE_DWORD_ALIGNED(type, p) (\
  494. reinterpret_cast<type>((reinterpret_cast<INT_PTR>(p) + 3) & ~3))
  495. // Adds the given number of bytes to a pointer
  496. #define ADD_POINTER(type, p, increment) (\
  497. reinterpret_cast<type>(reinterpret_cast<BYTE *>(p) + (increment)))
  498. #define ASSERT_DWORD_ALIGNED(p) ASSERTMSG(!(reinterpret_cast<INT_PTR>(p) & 3), ("'" #p "' not DWORD aligned"))
  499. #define ASSERT_QWORD_ALIGNED(p) ASSERTMSG(!(reinterpret_cast<INT_PTR>(p) & 7), ("'" #p "' not QWORD aligned"))
  500. // The variable-format structure for all batch record types.
  501. // Must be stored at a QWORD-aligned location
  502. struct EpScanRecord
  503. {
  504. UINT16 BlenderNum; // Identifies the AlphaBlender to be used to render
  505. // the scan. (0 through BlenderMax-1).
  506. UINT16 ScanType; // EpScanType explicitly coerced into 2 bytes.
  507. INT X;
  508. INT Y;
  509. INT Width; // Number of pixels to output
  510. INT OrgWidth; // The original width when the record was allocated.
  511. // (The width may change later, and we need the original
  512. // width in order to calculate the positions of
  513. // the variable-length records.)
  514. // Different scan types have different fields after the header:
  515. // 1) EpScanTypeOpaque, EpScanTypeBlend:
  516. // A color buffer, of "Width" pixels, in some pixel format. 8-byte aligned.
  517. // 2) EpScanTypeCT:
  518. // A color buffer, of "Width" pixels, in some pixel format. 8-byte aligned.
  519. // A CT coverage buffer, of "Width" bytes. 4-byte aligned.
  520. // 3) EpScanTypeCTSolidFill:
  521. // A CT coverage buffer, of "Width" bytes. 4-byte aligned.
  522. // Return the color buffer, of "Width" pixels. Valid for
  523. // EpScanTypeOpaque, EpScanTypeBlend and EpScanTypeCT.
  524. VOID *GetColorBuffer()
  525. {
  526. if (GetScanType() == EpScanTypeCTSolidFill)
  527. return NULL;
  528. return CalculateColorBufferPosition(
  529. this,
  530. GetScanType()
  531. );
  532. }
  533. EpScanType GetScanType()
  534. {
  535. return static_cast<EpScanType>(ScanType);
  536. }
  537. VOID SetScanType(EpScanType type)
  538. {
  539. ASSERT(type < (1<<sizeof(ScanType)));
  540. ScanType = static_cast<UINT16>(type);
  541. }
  542. // A safe way to set blenderNum - the cast is protected by an assertion.
  543. VOID SetBlenderNum(INT blenderNum)
  544. {
  545. ASSERT( (blenderNum >= 0)
  546. && (blenderNum < BlenderMax));
  547. BlenderNum = static_cast<UINT16>(blenderNum);
  548. }
  549. // Return the CT buffer, of "Width" pixels.
  550. // Valid for EpScanTypeCT and EpScanTypeCTSolidFill only.
  551. //
  552. // colorFormatSize - the size of a "color buffer" pixel, in bytes.
  553. BYTE *GetCTBuffer(
  554. INT colorFormatSize
  555. )
  556. {
  557. EpScanType type = GetScanType();
  558. ASSERT( (type == EpScanTypeCT)
  559. || (type == EpScanTypeCTSolidFill));
  560. if (type == EpScanTypeCT)
  561. {
  562. return CalculateCTBufferPosition(
  563. this,
  564. type,
  565. OrgWidth,
  566. colorFormatSize);
  567. }
  568. else
  569. {
  570. return CalculateCTBufferPositionCTSolidFill(this);
  571. }
  572. }
  573. // Calculates the position of the next scan record, given enough data
  574. // about the current one.
  575. //
  576. // This is like NextScanRecord, but it doesn't require the "currentRecord"
  577. // pointer to point to valid memory. Instead, the necessary data is
  578. // passed in parameters.
  579. //
  580. // Callers can use this to decide whether the record will fit into
  581. // available memory.
  582. //
  583. // currentRecord - points to the "current" record. This doesn't need
  584. // to be a valid record, and the memory it points to
  585. // doesn't need to be big enough to hold the current
  586. // record. Must be QWORD-aligned.
  587. // type - the type of record
  588. // width - the actual number of pixels
  589. // colorFormatSize - the size of a "color buffer" pixel, in bytes.
  590. static EpScanRecord *CalculateNextScanRecord(
  591. EpScanRecord *currentRecord,
  592. EpScanType type,
  593. INT width,
  594. INT colorFormatSize
  595. )
  596. {
  597. return InternalCalculateNextScanRecord(
  598. currentRecord,
  599. type,
  600. width,
  601. width,
  602. colorFormatSize);
  603. }
  604. // Returns a pointer to the next scan record, based on the current,
  605. // valid scan record.
  606. //
  607. // colorFormatSize - the size of a "color buffer" pixel, in bytes.
  608. EpScanRecord *NextScanRecord(
  609. INT colorFormatSize
  610. )
  611. {
  612. return InternalCalculateNextScanRecord(
  613. this,
  614. GetScanType(),
  615. Width,
  616. OrgWidth,
  617. colorFormatSize);
  618. }
  619. private:
  620. // These functions are 'static' to emphasize that they're usable on
  621. // EpScanRecord pointers which don't point to valid memory.
  622. // Calculates the position of the next scan record, given enough data
  623. // about the current one.
  624. //
  625. // currentRecord - points to the "current" record. This doesn't need
  626. // to be a valid record, and the memory it points to
  627. // doesn't need to be big enough to hold the current
  628. // record. Must be QWORD-aligned.
  629. // type - the type of record
  630. // width - the actual number of pixels
  631. // orgWidth - the "original" width - the width at the time the
  632. // scan was first allocated. Can't be smaller than
  633. // 'width'.
  634. // colorFormatSize - the size of a "color buffer" pixel, in bytes.
  635. static EpScanRecord *InternalCalculateNextScanRecord(
  636. EpScanRecord *currentRecord,
  637. EpScanType type,
  638. INT width,
  639. INT orgWidth,
  640. INT colorFormatSize
  641. )
  642. {
  643. ASSERT_QWORD_ALIGNED(currentRecord);
  644. EpScanRecord *p;
  645. // If width < orgWidth, we can reclaim some of the space at the end.
  646. // However, the record positions are based on orgWidth, so
  647. // only the final record can be shrunk.
  648. //
  649. // So, the pattern for the below is:
  650. // 1) Get the pointer to the last field, using "orgWidth".
  651. // 2) Add the field size, using "width" (not "orgWidth").
  652. // 3) QWORD-align it.
  653. switch (type)
  654. {
  655. case EpScanTypeBlend:
  656. case EpScanTypeOpaque:
  657. p = ADD_POINTER(
  658. EpScanRecord *,
  659. CalculateColorBufferPosition(currentRecord, type),
  660. width * colorFormatSize);
  661. break;
  662. case EpScanTypeCT:
  663. p = ADD_POINTER(
  664. EpScanRecord *,
  665. CalculateCTBufferPosition(
  666. currentRecord,
  667. type,
  668. orgWidth,
  669. colorFormatSize),
  670. width);
  671. break;
  672. case EpScanTypeCTSolidFill:
  673. p = ADD_POINTER(
  674. EpScanRecord *,
  675. CalculateCTBufferPositionCTSolidFill(
  676. currentRecord),
  677. width);
  678. break;
  679. }
  680. return MAKE_QWORD_ALIGNED(EpScanRecord *, p);
  681. }
  682. // Return a pointer to the color buffer. Valid for
  683. // EpScanTypeOpaque, EpScanTypeBlend and EpScanTypeCT.
  684. //
  685. // currentRecord - the "current" record, QWORD-aligned.
  686. // type - the type of record
  687. static VOID *CalculateColorBufferPosition(
  688. EpScanRecord *currentRecord,
  689. EpScanType type
  690. )
  691. {
  692. ASSERT_QWORD_ALIGNED(currentRecord);
  693. ASSERT( (type == EpScanTypeOpaque)
  694. || (type == EpScanTypeBlend)
  695. || (type == EpScanTypeCT));
  696. // Since the pointer is QWORD-aligned, we can do this by adding
  697. // the 'QWORD-aligned size' of this structure.
  698. //
  699. // The "regular" way would be to add the size and then
  700. // QWORD-align the pointer. But this is more efficient, because
  701. // qwordAlignedSize is a compile-time constant.
  702. const INT qwordAlignedSize = (sizeof(EpScanRecord) + 7) & ~7;
  703. return ADD_POINTER(VOID *, currentRecord, qwordAlignedSize);
  704. }
  705. // Return a pointer to the CT buffer.
  706. // Valid for EpScanTypeCT only.
  707. //
  708. // currentRecord - the "current" record, QWORD-aligned.
  709. // type - the type of record
  710. // width - the number of pixels
  711. // colorFormatSize - the size of a "color buffer" pixel, in bytes.
  712. static BYTE *CalculateCTBufferPosition(
  713. EpScanRecord *currentRecord,
  714. EpScanType type,
  715. INT width,
  716. INT colorFormatSize
  717. )
  718. {
  719. ASSERT_QWORD_ALIGNED(currentRecord);
  720. ASSERT(type == EpScanTypeCT);
  721. BYTE *p = ADD_POINTER(
  722. BYTE *,
  723. CalculateColorBufferPosition(currentRecord, type),
  724. colorFormatSize * width);
  725. return MAKE_DWORD_ALIGNED(BYTE *, p);
  726. }
  727. // Return a pointer to the CT buffer, of "Width" pixels.
  728. // Valid for EpScanTypeCTSolidFill only.
  729. //
  730. // currentRecord - the "current" record, QWORD-aligned.
  731. // type - the type of record
  732. // width - the number of pixels
  733. // colorFormatSize - the size of a "color buffer" pixel, in bytes.
  734. static BYTE *CalculateCTBufferPositionCTSolidFill(
  735. EpScanRecord *currentRecord
  736. )
  737. {
  738. ASSERT_QWORD_ALIGNED(currentRecord);
  739. BYTE *p = reinterpret_cast<BYTE *>(currentRecord+1);
  740. ASSERT_DWORD_ALIGNED(p);
  741. return p;
  742. }
  743. };
  744. // Queue data structures:
  745. enum GdiDciStatus
  746. {
  747. GdiDciStatus_TryDci, // We're to try using DCI, but it hasn't been
  748. // initialized yet (which if it fails will
  749. // cause us to fall back to GDI)
  750. GdiDciStatus_UseDci, // We successfully initialized DCI, so use it
  751. // for all drawing
  752. GdiDciStatus_UseGdi, // Use only GDI for all drawing
  753. };
  754. // Minimum buffer size for the DCI drawing queue:
  755. #define SCAN_BUFFER_SIZE 64*1024
  756. class EpScanGdiDci : public EpScan
  757. {
  758. private:
  759. // Persistent state:
  760. GdiDciStatus Status; // Class status
  761. GpDevice* Device; // Associate device; must exist for
  762. // the lifetime of this object
  763. DpContext* Context; // Points to the context object related
  764. // to any records sitting in the batch.
  765. // May be invalid if the batch is
  766. // empty.
  767. DpBitmap* Surface; // Similarly points to the surface
  768. // related to any records sitting in
  769. // the batch.
  770. BOOL IsPrinter; // Is the destination a printer?
  771. DCISURFACEINFO *DciSurface; // DCI surface state, allocated by
  772. // DCI
  773. INT PixelSize; // Pixel size, in bytes for the current
  774. // batch record
  775. VOID *Buffers[5]; // Temporary scan buffers
  776. // Cache objects:
  777. HRGN CacheRegionHandle; // Region we hang on to so that we
  778. // don't have to re-create on every
  779. // query
  780. RGNDATA *CacheRegionData; // Clipping data allocation (may be
  781. // NULL)
  782. INT CacheDataSize;
  783. RECT *EnumerateRect;
  784. INT EnumerateCount;
  785. // Bounds accumulation:
  786. INT MinX;
  787. INT MaxX;
  788. INT MinY;
  789. INT MaxY; // Note that YMax is 'inclusive'
  790. // Global offset for the batch processing.
  791. INT BatchOffsetX;
  792. INT BatchOffsetY;
  793. // For *SolidFill scan types, we need to record the solid color passed
  794. // to Start(). We use it when we call EpAlphaBlender::Initialize()
  795. ARGB SolidColor;
  796. // Enumeration information:
  797. VOID *BufferMemory; // Points to start of buffer memory
  798. // block
  799. EpScanRecord *BufferStart; // Points to queue buffer start.
  800. // QWORD-aligned.
  801. EpScanRecord *BufferEnd; // Points to end of queue buffer
  802. EpScanRecord *BufferCurrent; // Points to current queue position
  803. INT BufferSize; // Size of queue buffer in bytes
  804. private:
  805. VOID *NextBuffer(
  806. INT x, INT y,
  807. INT newWidth,
  808. INT updateWidth,
  809. INT blenderNum
  810. );
  811. VOID LazyInitialize();
  812. VOID EmptyBatch();
  813. VOID DownloadClipping_Dci(HDC hdc, POINT *clientOffset);
  814. VOID ProcessBatch_Dci(HDC hdc, EpScanRecord* bufferStart, EpScanRecord* bufferEnd);
  815. BOOL Reinitialize_Dci();
  816. VOID LazyInitialize_Dci();
  817. EpScanRecord* FASTCALL DrawScanRecords_Dci(
  818. BYTE* bits, INT stride,
  819. EpScanRecord* record,
  820. EpScanRecord* endRecord,
  821. INT xOffset, INT yOffset,
  822. INT xClipLeft, INT yClipTop,
  823. INT xClipRight, INT yClipBottom
  824. );
  825. VOID ProcessBatch_Gdi(
  826. HDC hdc,
  827. EpScanRecord* bufferStart,
  828. EpScanRecord* bufferEnd
  829. );
  830. // Perform SrcOver blend using GDI for 32bpp (P)ARGB source pixels only.
  831. VOID SrcOver_Gdi_ARGB(
  832. HDC destinationHdc,
  833. HDC dibSectionHdc,
  834. VOID *dibSection,
  835. EpScanRecord *scanRecord
  836. );
  837. public:
  838. // Pass TRUE for 'tryDci' if it's okay to try using DCI for our rendering;
  839. // otherwise only use GDI:
  840. EpScanGdiDci(GpDevice *device, BOOL tryDci = FALSE);
  841. ~EpScanGdiDci();
  842. virtual BOOL Start(
  843. DpDriver *driver,
  844. DpContext *context,
  845. DpBitmap *surface,
  846. NEXTBUFFERFUNCTION *getBuffer,
  847. EpScanType scanType,
  848. PixelFormatID pixFmtGeneral,
  849. PixelFormatID pixFmtOpaque,
  850. ARGB solidColor
  851. );
  852. virtual VOID End(INT updateWidth);
  853. virtual VOID* GetCurrentBuffer()
  854. {
  855. return BufferCurrent->GetColorBuffer();
  856. }
  857. virtual BYTE* GetCurrentCTBuffer()
  858. {
  859. // We assume that in ClearType cases,
  860. // there is only one scan type for the Start()...End() sequence
  861. ASSERT(BufferCurrent->BlenderNum == 0);
  862. // This should only be called for ClearType scan types
  863. ASSERT( (BlenderConfig[0].ScanType == EpScanTypeCT)
  864. || (BlenderConfig[0].ScanType == EpScanTypeCTSolidFill));
  865. ASSERT(BlenderConfig[0].ScanType == BufferCurrent->GetScanType());
  866. return BufferCurrent->GetCTBuffer(
  867. GetPixelFormatSize(BlenderConfig[0].SourcePixelFormat) >> 3
  868. );
  869. }
  870. virtual VOID Flush();
  871. // This function processes an entire batch of scans -
  872. // it handles multiple pixel formats and combinations
  873. // of SourceOver and SourceCopy.
  874. virtual BOOL ProcessBatch(
  875. EpScanRecord *batchStart,
  876. EpScanRecord *batchEnd,
  877. INT minX,
  878. INT minY,
  879. INT maxX,
  880. INT maxY
  881. );
  882. };
  883. #endif // !_SCAN_HPP