-
> [79] oxffff © (23.03.08 21:33)
вот у него и поинтересуйтесь ) вот чего он не содержит, так это картинки с изображением окна. Ну не кэширует виндовз это и все тут.. на этом уровне абстракции по крайней мере, уверен, что на более низком уровне растры кэшируются графической подсистемой, но не здесь.
-
oxffff © (23.03.08 21:33) [79] Кстати, еще: Та же программа с небольшими изменениями, перечисляющая окна и пытающаяся вывести кусок с DC function EnumWindowProc (Wnd: HWND; param: LPARAM): Integer; stdcall;
var
AClassName: array[0..255] of char;
CS: DWORD;
begin
with TForm1(param) do
begin
GetClassName(Wnd, AClassName, SizeOf(AClassName));
CS := GetClassLong(Wnd, GCL_STYLE);
if (CS and (CS_OWNDC or CS_CLASSDC)) <> 0 then
ListBox1.Items.AddObject(AClassName, TObject(Wnd));
end;
Result := 1;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Wnd: HWND;
ADC: HDC;
begin
if ListBox1.ItemIndex > -1 then
begin
Wnd := HWND(ListBox1.Items.Objects[ListBox1.ItemIndex]);
if IsWindow(Wnd) then
begin
ADC := GetDC(Wnd);
try
with PaintBox1.ClientRect do
BitBlt(PaintBox1.Canvas.Handle, Left, Top, Right - Left,
Bottom - Top,
ADC, 0, 0, SRCCOPY);
finally
ReleaseDC(Wnd, ADC);
end;
end;
end;
end; У меня в ListBox три окна - ConsoleWindowClass от Far, MsoCommandBarPopup от Help по Delphi 2006 и ConsoleWindowClass от Apache, запущенного в консоли. Окно FAR не полноэкранное и перекрыто нижним краем окна программы. При нажатии на кнопку в PaintBox рисуется как часть окна Far, так и краешек окна программы, которым перекрыто окно Far. Меня это приводит к выводу о том, что буфер - он для растра, а не для каждого DC :) На этой оптимистической ноте закончим дискуссию ?
-
Попытаюсь подвести итог: Большинство операций рисования GDI вызывает обновление буфера растра. В зависимости от возможностей драйвера видеокарты, эти операции обновления отдаются либо драйверу напрямую, чтобы рисование выполнялось с использованием процессора видеокарты, либо GDI рисует по своим алгоритмам, используя процессор собственно компьютера и пересылает сформированное изображение в видеопамять. При установленном свойстве DoubleBuffered все рисование с точки зрения GDI выполняется одной операцией BitBlt, поэтому буфер растра обновляется один раз и результаты промежуточных операций на экране не мелькают.
-
Сохраню-ка я эту веточку для повышения образованности. Опять же много пользительных ссылок приведено... :-)
-
> [77] Игорь Шевченко © (23.03.08 20:38)
> Но в двух словах. если говорить о DC и об окнах, то буфер > есть у растра, весьма вероятно, что физически оно живет > у того самого DC, который по CreateDC('DISPLAY') создается. > Все оконные DC представляют "окна" (пардон за тавтологию) > в этот буфер, с границами, определямыми регионами отсечения.
Фэнь с вами согласен. Вероятно вы достаточно четко представляете себе отличия между контекстом устройства, связанным с конкретным окном, и контекстом, созданным функцией CreateDC. Главное отличие заключается в том, что к числу атрибутов первого относится прямоугольник вывода, являющийся подмножеством поверхности устройства, и объединенный видимый регион, который строится с учетом таких факторов, как регион окна, отсечение соседних и дочерних окон, видимых частей и обновляемого региона окна.
-
> Eraser © (23.03.08 21:37) [80] > > [79] oxffff © (23.03.08 21:33) > > вот у него и поинтересуйтесь ) > вот чего он не содержит, так это картинки с изображением > окна. Ну не кэширует виндовз это и все тут.. на этом уровне > абстракции по крайней мере, уверен, что на более низком > уровне растры кэшируются графической подсистемой, но не > здесь.
читать про Private Device Contexts и их отличие от Common Device Contexts.
-
> Меня это приводит к выводу о том, что буфер - он для растра, > а не для каждого DC :) > > На этой оптимистической ноте закончим дискуссию ?
Так я вам об этом выше написал. см. oxffff © (23.03.08 20:10) [68]
Но разговор был о том, есть некий DC SHARED растр, пусть он будет большой и разделяемый не суть важно.
Важно, что есть буфер который -> копируется в видепамять.
-
> Игорь Шевченко © (23.03.08 22:01) [82]
Именно это мнение я и разделяю. Поэтому при double buf буфферов может быть 2 и 3 с учетом front buf video.
-
> [85] oxffff © (23.03.08 22:09)
ну есть отличие, только поясните, какое это отношение имеет к теме, в частности, двойной буфферизации? что-то я не уловил момент..
-
> Eraser © (23.03.08 22:16) [88]
[37] [39] [40]
-
> [89] oxffff © (23.03.08 22:21)
вы не путаете кэширование gdi операций с кэшированием готовых растров? к слову в висте реализовали системный механизм растровой буфферизации, который успешно применяется в CDS2007, см. BeginBufferedPaint.
-
> Eraser © (23.03.08 22:29) [90]
Разговор у нас о DC и DC bitmap. Я вас не понял.
-
Честно говоря я думал, что под Device (в DC) подразумевается некое устройство (экран, окно, принтер, битмэп, метафайл) для возможности универсально "рисовать" на них. Иначе говоря, я думал, что bitmap в данном случае - лишь один из вариантов того, на чем можно рисовать с помощью DC. И, честно говоря, ранее меня не смущало, что битмэп привязывается к ДЦ с помощью функции SelectObject. Поправьте меня, если я не прав.
-
to Eraser
Offtop
BeginBufferedPaint
Ну насколько я понял назначение этой функции в том, чтобы обеспечить предварительную отрисовку содержимого в буфере видеокарты, а поскольку скорее всего все операции будут аппаратно поддержаны то сократится количество пересылок RAM -> VIDEO RAM. Что хорошо скажется на производительности.
Наш разговор был не об этом. :)
-
> [89] oxffff © (23.03.08 22:21)
> [37] [39] [40]
не пойму в чем "фишка" этого примера? ведь он только доказывает, то, что уже несколько раз проверял Игорь - копируется только то, что видимо. вот моя модификация
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Memo1: TMemo;
Button2: TButton;
procedure Button2Click(Sender: TObject);
protected
procedure CreateParams (var Params: TCreateparams); override;
private
public
end;
var
Form2: TForm2;
implementation
procedure TForm2.Button2Click(Sender: TObject);
const
WindowName = 'DMClient';
var
WindowRect: TRect;
hWnd: THandle;
begin
hWnd := FindWindow(nil, WindowName);
GetWindowRect(hWnd, WindowRect);
StretchBlt(GetDC(Memo1.Handle), 0, 0, Memo1.Width,
Memo1.Height,
GetDC(hWnd),
Memo1.Left, Memo1.Top, Memo1.Width,
Memo1.Height, SRCCOPY);
end;
procedure TForm2.CreateParams(var Params: TCreateparams);
begin
inherited;
Params.WindowClass.style := Params.WindowClass.style or CS_OWNDC;
end;
end.
окно DMClient'а видно только если оно на видимо и только те части, которые не скрыты другими окнами, ч.т.д. > BeginBufferedPaint > > Ну насколько я понял назначение этой функции в том, чтобы > обеспечить предварительную отрисовку содержимого в буфере > видеокарты, а поскольку скорее всего все операции будут > аппаратно поддержаны то сократится количество пересылок > RAM -> VIDEO RAM.
думаю да, реализация этой функции не многим отличается от того, что реализовано в VCL для более старых версий системы. Там вроде можно указать какой именно тип битмапа применять для кэширования, к примеру BPBF_DIB или BPBF_COMPATIBLEBITMAP.
-
> [92] Дмитрий С (23.03.08 22:38)
все правильно, контекст устройство это инструмент для рисования, а не холст. Холст (битмап) к нему можно привязать, но не ко всякому контексту, а только в compatable... BeginBufferedPaint позволяет обойти это ограничение, но только благодаря своим механихмам и для целей буфферизации, хотя возможно как то и можно добраться до внутреннего буффера, используемого этой функцией.
-
Кстати, то что оконный DC представляет собой дырку в общий DC объясняет и то, что в оконный DC нельзя выбрать BITMAP - а чего с ним потом делать, с выбранным BITMAP'ом ? :)
oxffff © (23.03.08 22:13) [86]
> Важно, что есть буфер который -> копируется в видепамять.
Или не копируется - какой смысл занимать центральный процессор рисованием в этом буфере, если процессор видеокарты поддерживает массу операций GDI ?
Когда GDI (внутри ядра) уже посчитал отсечения и решил, что нужно вызывать драйвер для рисования, он вызывает одну из известных функций. При инициализации видеоподсистемы драйвер видеокарты записывает в адреса этих известных функций те, которые он поддерживает. Которые не поддерживает, остаются для реализации алгоритмов GDI средствами центрального процессора. Фэнь Юань про этот процесс пишет более подробно.
Так вот - если драйвер не чего-то поддерживает, то буфер растра будет и GDI будет на нем рисовать и отсылать драйверу в виде внутренней BitBlt - это вроде все поддерживают. А если драйвер поддерживает какие-то операции GDI, то и буфера растра не будет - все рисование будет выполняться видеокартой.
-
> вот моя модификация
А что DMClient со стилем CS_OWNDC? Перечитай еще раз внимательно. :)
-
> Игорь Шевченко © (23.03.08 23:03) [96]
Это то понятно. Меня больше интересует вопрос более серьезный. А как быть если часть операций поддерживается, а часть нет. Часть операций видеокартой в VIDEO буфере, а часть в RAM буфере, Как потом смешивать результаты? :)))))))
-
> [97] oxffff © (23.03.08 23:05)
пардон, моя вина.. невнимательность, но суть дела это не поменяло.. даже если заменить WindowName = 'DMClient'; на WindowName = 'Form2'; эффект тот же - скрытая часть окна не копируется.
|