HPC.ru lite - Все форумы
Форум: Программирование для КПК
Тема: "продвинутое рисование на форме"
Страницы: 1 [2]
[Ответить]
sshd [13.04.2006 13:20] :
ВадимП писал(а):
И я не вижу абсолютно никаких преимуществ в первом предложенном варианте - напротив, только недостатки в частности за счет дополнительных потерь времени на копирование.
Переключать буфера на мой взгляд гораздо удобнее и проще.
(никаких проблем с созданием необходимого числа буферов и свободным переключением между ними, по крайней мере, на Linux-КПК нет - начало отображаемой части видеопамяти определяется указателем screen_base, который используется низкоуровневым драйвером кадрового буфера).
тоесть ты предлагаешь перерисовывать _весь_ экран????
во-первых на покете это вроде бы нельзя делать, во-вторых я так понял, что нужно рисовать в окошке.
page flipping вообще какая-то древняя технология. на спектруме была.
sshd [13.04.2006 13:22] :
apachik писал(а):
работает
. только вот DrawImage тормозит. можно побыстрее сделать?
можно.
использовать native code.
ВадимП [13.04.2006 17:31] :
sshd писал(а):
во-вторых я так понял, что нужно рисовать в окошке.
page flipping вообще какая-то древняя технология. на спектруме была.
Да-да, совсем древняя... Вся трехмерная графика (во всяком случае OpenGL) именно на ней и построена - Вы же пишете при инициализации окна glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
а потом по мере надобности glutSwapBuffers();
(для краткости привожу примеры с использованием библиотеки GLUT, но идея от этого не меняется - могу переписать то же самое на чистом GLX. Только длиннее будет)
Создаём область видеопамяти с двойной буферизацией:
Display *dpy;
Screen *scr;
int scrnum;
int attrib[] = { GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 1,
None };
XVisualInfo *visinfo;
scrnum = XScreenNumberOfScreen(scr);
root = XRootWindow(dpy, scrnum);
visinfo = glXChooseVisual( dpy, scrnum, attrib );
прим: для краткости я не стал записывать API создающие окно на базе этого visual.
А потом, после окончания формирования изображения на экране, пишем glXSwapBuffers(dpy, win);
Кстати, независимо от того, перерисовываем ли мы весь экран или небольшой его кусочек - для этого существуют такие инструменты как ножницы (scissors) и трафаретный буфер (stencil buffer).
(трехмерные игры-то спокойно запускаются в окне и двойная буферизация в видеопамяти этому не мешает)
Я конечно понимаю, что исходный вопрос не имел никакого отношения к трехмерной графике и что видеоподсистемы КПК не обеспечивают, увы, необходимой аппаратной поддержки для реализации подобных средств (хотя последнее-то как раз и не имеет особого значения - библиотеки при необходимости эмулируют недостающие возможности программно). Я просто хотел поддержать уважаемого sshd в том, что подобная техника - это несомненно самый что ни на есть каменный век и всяким там doom'ам 3 и quake'ам 4 если и осталось место, то именно на Spectrum'ах! 
apachik [13.04.2006 17:43] :
sshd писал(а):
тоесть ты предлагаешь перерисовывать _весь_ экран????
во-первых на покете это вроде бы нельзя делать, во-вторых я так понял, что нужно рисовать в окошке.
page flipping вообще какая-то древняя технология. на спектруме была.
мне нужно перерисовывать почти весь экран - кроме нижней строки с меню и верхней информационной строки (там всякие лэйблы). строка с заголовком окна убрана нах.
apachik [13.04.2006 18:06] :
вот что я нашел
http://www.codeproject.com/bitmap/drawing_without_flicker.asp
Explanation of Double Buffering
If you have to draw repeatedly to the screen in a short period of time, then when you keep drawing step by step to the DC, it updates the Window again and again which makes the screen flicker.
To avoid this, we first draw to a DC in memory (see the CDC MemDC and CBitmap MemBitmap declarations), and we store the resultant drawing in a memory bitmap. After all the drawing has been completed, we move the bitmap from the memory to the screen in a fast single bitblt call. Thus, we only need to draw once to the screen which avoids flickering totally. This principle is called Double Buffering.
Example code
This example assumes that you are going to draw filled rectangles onto the screen. It generates random shades of green to fill that rectangle.
Use this code in your view class's OnDraw() function if you are using Doc/View architecture or if you are using a dialog based application, then you can add this code in the OnPaint Function.
CRect rcClient;
GetClientRect(rcClient); // See Note 1
CDC MemDC,*pDC;
CBitmap MemBitmap;
pDC = this->GetDC() // Get Current DC
MemDC.CreateCompatibleDC(pDC);
MemBitmap.CreateCompatibleBitmap(pDC,rcClient.right,rcClient.bottom);
CBitmap *pOldBitmap = MemDC.SelectObject(&MemBitmap);
CBrush bkBrush(HS_FDIAGONAL,RGB(0,rand()%255,0)); // See Note 2
MemDC.FillRect(rcClient,&bkBrush);
pDC->BitBlt(0,0,rcClient.right,rcClient.bottom,&MemDC,0,0,SRCCOPY); //See Note 3
MemDC.SelectObject(pOldBitmap);
Note 1 : Gets the coordinates of the bounding rectangle.
Note 2 : Creates a brush with random shades of green. The rand()%255 generates a value between 0 and 255 randomly.
Note 3 : Copies the bitmap from the memory dc to the pdc using a fast bitblt function call.
но это все для С++
apachik [13.04.2006 18:14] :
sshd писал(а):
[quote:e4726ac758="apachik"]работает
. только вот DrawImage тормозит. можно побыстрее сделать?
можно.
использовать native code.
не понял. что значит native code?
предлагаешь отказаться от .НЕТ?
apachik [13.04.2006 18:27] :
вот еще что нашел:
http://www.codeproject.com/cs/media/flickerFreeDrawing.asp
Introduction
This article describes how to implement flicker free drawing on Windows Forms using GDI+, it assumes you have a basic understanding or VS.NET, C# and the .NET framework.
Background
Flicker free drawing or double buffering is a well know technique used in the Windows programming world to reduce flicker when handling paint events in a window.
Normally a generic window programs draw directly to the device context (Graphics Object) when a WM_PAINT (Paint) event occurs. This can lead to flickering if the window is refreshed (Invalidated) repeatedly. Three examples where flickering happen would be during a Window resize or animation (a timer is fired and in the timer event the window is refreshed) or when a object is dragged over the window (e.g. Visio)
We can eliminate flickering using a technique known as double buffering. Rather than drawing directly on the graphics object, we draw to an off screen graphics object and when the drawing is complete we draw the off screen graphics object onto the graphics object supplied by the Paint event. We also override the OnPaintBackground method to prevent the windows form performing any background rendering (we must paint the background ourselves during the rendering in the off screen graphics object, this is usually the first thing that is done).
The double buffering technique is encapsulated in a simple class called DBGraphics and can be easily implemented in a typical windows form based application show below.
Using the code
The double buffering class can be used within the scope of the windows form. The steps below describe how to implement the DBGraphics class in your code:
Step 1 - Declare the DBGraphics variable in your windows form class and instantiate the object in the windows form constructor.
using GDIDB; // Declare the namespace
public class MainWnd : System.Windows.Forms.Form
{
... Some other code
private DBGraphics memGraphics;
... Some other code
public MainWnd()
{
memGraphics = new DBGraphics();
}
};
Step 2 - Handle the resize and load event to create the double buffer object to the size of the Client Rectangle. This is done in form load event as the resize event only gets fire when the form is manually resized. One thing to note here is we need to obtain the graphics object of the form even though we are not in the Paint event, this done by calling this.CreateGraphics()is is similar to GetDC().
private void MainWnd_Load(object sender, System.EventArgs e)
{
<B> memGraphics.CreateDoubleBuffer(this.CreateGraphics(), this.ClientRectangle.Width, this.ClientRectangle.Height);
</B>}
private void MainWnd_Resize(object sender, System.EventArgs e)
{
<B> memGraphics.CreateDoubleBuffer(this.CreateGraphics(), this.ClientRectangle.Width, this.ClientRectangle.Height);
</B> Invalidate(); // Force a repaint after has been resized
}
Step 3 - Override the OnPaintBackground is to allow the paint event to render the background.
<B>protected override void OnPaintBackground(PaintEventArgs pevent)
{
}</B>
Step 4 - Finally implement the Paint event
protected override void Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
<B> if (memGraphics.CanDoubleBuffer())
{
// Fill in Background (for effieciency only the area that has been clipped)
memGraphics.g.FillRectangle(new SolidBrush(SystemColors.Window), e.ClipRectangle.X,e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height);
// Do our drawing using memGraphics.g instead e.Graphics
... Some other code
// Render to the form
memGraphics.Render(e.Graphics);
}
</B>}
только вот с делкарацией GDIDB какие то непонятки
zobot [18.04.2006 15:12] :
подскажите плиз как сделать синхронизацию по кадровой развёртке (аля как на больших кампиках синхронизация по регистру Vertical blanking видязи в досе и direct draw).
Чё-т не могу найтить...
[Ответить]
[< Назад]