Re: Why use OpenGL (was Native Mode Handling)

Brian Paul <brian-CdwZJljFklH+2FeEXyspIVaTQe2KTcn/@public.gmane.org>
Newsgroups gmane.comp.freedesktop.xserver
Organization Tungsten Graphics, Inc.
Message-ID <[email protected]>
Kendall Bennett wrote:
> Brian Paul <brian-CdwZJljFklH+2FeEXyspIVaTQe2KTcn/@public.gmane.org> wrote:
> 
> 
>>>Thinking about this some more it would seem to me that perhaps what you
>>>need is to make sure there is always a good 2D API available that is
>>>implemented in terms of 3D functionality. Make sure it is easy to use
>>>(or backwards compatible at least), and make sure it can be done *fast*.
>>>Like I mentioned before, bitmap support in OpenGL sucks -
>>
>>Can you elaborate?  I've heard this said before, but I never see
>>much in the way of concrete information. 
> 
> 
> Doing it fast via OpenGL is always painful, because glDrawPixels is 
> traditionally not well accelerated (even on Windows).

Actually, it's not too bad with recent NVIDIA and ATI drivers (for 
example).

The basic task is to quickly move image data from user space to VRAM. 
  There's no reason why OpenGL should be slower than any other 
graphics library/API for comparable operations.


> Part of it has to 
> do with the fact that at the back end doing *everything* this function 
> can do is complicated, so the hardware drivers have to know what common 
> fast cases should be accelertaed, and the call code needs to know what 
> state to set up in order to get on the fast path.

This is doable.  It's just a matter of using the "right" OpenGL image 
format/type.  I'd expect the fast format/type combinations to be the 
same as those for GDI or DirectX or Xlib or whatever API people are 
using nowadays.


>>>One way of thinking about this is that as a 2D programmer, if I want to
>>>draw a blended 2D bitmap, I don't want to have to set up a geometry
>>>pipeline, load a texture map, bind the texture map, set up the 3D
>>>rendering engine state and then finally draw some 3D triangles to get my
>>>blended bitmap on the screen. Rather I just want to call something like
>>>BlendBitmap() that will take my bitmap and blend it onto the screen.
>>>Whether the internal implementaiton does all of the above is irrelevant,
>>>so long as the 2D programmer does not have to deal with all the 3D
>>>cruft.
>>
>>What's wrong with this:
>>
>>glEnable(GL_BLEND);
>>glWindowPos2i(x,y);
>>glDrawPixels( my_image );
> 
> 
> What about all the rest of the state that has to be set up correctly to 
> ensure this works properly?

The default state should be OK.  If you're mucking with other state 
(like alpha test, z-test, etc) then as the programmer you're obligated 
to take care to set things correctly.  That's true no matter what API 
you're using.


> There are all kinds of raster modes and 
> scaling that can affect this call that needs to be accounted for, plus 
> you need to set up the blending pipeline correctly.

Sure, you have to set the right blend mode.  But you'd have to do that 
with any API you'd use.


> On top of that all 
> this ends up going through the geometry pipeline (since the vertices 
> *can* be transformed in OpenGL for this function I believe).

glWindowPos is extremely simple/fast.


> Since most 
> developers using a 2D API could care less about sub pixel precision etc.

OK, so the programmer uses glWindowPos and they don't have to care.


> Also using glDrawPixels() the only option you have is to draw the bitmap 
> from a image buffer that you pass to the OpenGL API. There is no way to 
> create a bitmap and have the contents stored in offscreen video memory 
> somewhere, and then be able to draw directly from the offscreen buffer 
> somewhere else in video memory using the hardware. To do that, you need 
> to stuff your bitmap into a texture (with all the associated hazards of 
> texture dimensions), bind it to the pipeline and then draw some polygons. 
> Like I said before, whether intenally a DrawBitmap function does all of 
> that is irrelevant - the 2D programmer does not want to have to deal with 
> that level of complexity.

The GL_ARB_vertex_buffer_object extension will probably soon have a 
layered extension that will effectively let you store an image in 
video memory and reference it with glDrawPixels.  It would be 
analogous to X's Pixmaps.

A smart display list implementation could do this too.

You might say that this sounds complicated.  But how would you do this 
with any other graphics library?  With Xlib you'd use a Pixmaps. 
You'd create a pixmap with XCreatePixmap(), load its contents with 
XPutImage(), then draw it to the framebuffer with XCopyArea().  Anyone 
who's done this knows that it's not exactly simple.

Incidently, using texture maps to store images on the server side and 
drawing them with a textured polygon might be substantially faster 
than a conventional blit.  Does blit performance on modern cards 
approach the giga-pixel fill rate that can be realized with texture 
mapping?

The other advantage of texture mapping over glDrawPixels (for images 
drawn more than just once) is the fact that OpenGL can reformat the 
image data if it's not in the ideal format.

To summarize my position:

- OpenGL's API is pretty simple for most things (far simpler than 
Xlib, for example).  You can generally ignore the parts that you don't 
need.
- There's no intrinsic reason why OpenGL should be slow when it comes 
to conventional 2D image operations.
- We have the know-how to optimize some of these things in our GL 
drivers.  It's just a matter of finding the time.  I bet that if we 
implemented fast glDraw/Copy/ReadPixels in one of the DRI drivers, 
other people could adapt the implementation to other drivers pretty 
quickly.

-Brian
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.