Compare commits

...

245 Commits

Author SHA1 Message Date
Keith Whitwell
8ecd83f6cd silence debug messages 2006-03-29 21:27:09 +00:00
Brian Paul
cff7e025ed fix ReadBuffer mapping bugs 2006-03-29 21:22:05 +00:00
Thomas Hellström
3de9a9bd1d Bump driver date.
Keep the lock mutex locked while we hold the heavyweight lock.
2006-03-29 21:21:54 +00:00
Keith Whitwell
e6cae6e6f6 Turn compiler optimizations back on. 2006-03-29 21:09:14 +00:00
Thomas Hellström
9cf5945b83 Age the last_swap_fence properly.
Should be safe unless the client idles without rendering for some
time, while another client renders.
2006-03-29 13:20:50 +00:00
Keith Whitwell
d6ddc33f07 Protect the DRI __driUtilUpdateDrawable code and other "complex" code
inside intelGetLock() with a mutex.  Fixes problems with multithreaded
applications dying when moving windows, etc.  There seem to be multiple
traps for threaded apps in that code, this is a bandaid on those.
2006-03-27 18:31:27 +00:00
Brian Paul
ec32d129b7 remove a temporary FBO test in intel_map_unmap_buffers() - fixes flickering in tunnel demo 2006-03-27 14:48:22 +00:00
Thomas Hellström
cd41c27446 zero-valued fences are not considered retired for a system that has been
running for a day or so. Initialize to a better value.
2006-03-27 13:55:45 +00:00
Brian Paul
af6a480117 remove some unneeded code 2006-03-26 05:15:21 +00:00
Brian Paul
14e9700621 merge from trunk 2006-03-25 23:48:18 +00:00
Brian Paul
7fb177c367 Shorten ctx->Driver.RenderbufferTexture to ctx->Driver.RenderTexture since
calls to it no longer directly correspond to glRenderbufferTextureEXT.
2006-03-25 22:14:09 +00:00
Brian Paul
d65cda4ce3 Implement software fallback for render-to-texture when the texture format
can't be rendered by the hardware.
2006-03-25 17:56:49 +00:00
Brian Paul
460a375d85 fix a couple issues in _mesa_free_framebuffer_data() 2006-03-25 17:55:07 +00:00
Brian Paul
c3c5652602 comments 2006-03-25 16:21:07 +00:00
Brian Paul
e1998baef8 Implement rendering to textures for any mipmap level, any cube face, any
3D texture slice.
Added draw_offset to intel_region struct.
2006-03-25 16:20:27 +00:00
Brian Paul
3e980901b0 check if copying from FBO, adjust x, y accordingly 2006-03-25 16:19:07 +00:00
Brian Paul
14fe63a12b Check for incomplete framebuffer in _mesa_Clear() 2006-03-25 16:13:45 +00:00
Brian Paul
fbd147c0b5 unlock mutex before freeing data (caught w/ valgrind) 2006-03-25 15:40:24 +00:00
Brian Paul
7b7c54e94c Replace _mesa_destroy_context() with _mesa_free_context_data() because ctx
is a member of the intel_context struct and the former calls frees the
ctx pointer - BAD.
2006-03-25 15:37:33 +00:00
Brian Paul
84dd9c8112 silence several -pedantic warnings 2006-03-25 15:10:35 +00:00
Brian Paul
bba85343e7 remove stray semicolon 2006-03-25 15:05:07 +00:00
Brian Paul
6484b373c3 s/inline/INLINE/ to allow use of -ansi flag with gcc. 2006-03-25 15:01:42 +00:00
Brian Paul
245a3c54c7 merge from trunk 2006-03-24 23:57:20 +00:00
Brian Paul
1266e633cc In i915/i830_update_tex_unit() get the firstImage pointer _after_ we've called
intel_finalize_mipmap_tree().
This fixes a problem where the wrong mipmap level was used when the
texture's GL_TEXTURE_BASE_LEVEL value wasn't zero.  But this only happened
the first time the texture was used.  That took a while to track down!
2006-03-24 23:43:16 +00:00
Brian Paul
86042f53f2 added some missing formats in _mesa_source/dest_buffer_exists() 2006-03-24 22:51:49 +00:00
Brian Paul
068062f997 better switch cases 2006-03-24 22:33:03 +00:00
Brian Paul
c62af8e3b7 update scissor at end of intel_draw_buffer() 2006-03-24 22:32:24 +00:00
Brian Paul
8e5650d7f4 no need to pass ctx to _mesa_clip_to_region() 2006-03-24 22:30:55 +00:00
Brian Paul
65f1cf2cbf update i915/i830Scissor to use DrawBuffer instead of driDrawable bounds 2006-03-24 22:03:22 +00:00
Brian Paul
f04f5e990a minor clean-ups 2006-03-24 16:51:51 +00:00
Brian Paul
1854ebe77e more fixes and clean-up in intelCopyBuffer() 2006-03-24 14:42:04 +00:00
Brian Paul
3500f2e3c4 some comments 2006-03-23 23:23:18 +00:00
Brian Paul
cfeefc9b81 just comments 2006-03-23 23:17:57 +00:00
Brian Paul
3ad6adfb57 another intelFlush() call 2006-03-23 23:11:50 +00:00
Brian Paul
8a126f1166 fix some mapping bugs 2006-03-23 23:11:30 +00:00
Brian Paul
6315aabcf2 check for NULL rb in _mesa_framebuffer_renderbuffer() 2006-03-23 23:11:07 +00:00
Brian Paul
a8c2344364 Added an intelFlush() call inside intel_bind_framebuffer() to be sure
any previous rendering is completed.  Not sure why this is needed when
_mesa_BindFramebufferEXT() does a FLUSH_VERTICES() call.
This fixes an offset/wrap-around bug when rendering to FBOs.
2006-03-23 22:33:58 +00:00
Brian Paul
2929b2569b added render/framebuffer locking for thread safety 2006-03-23 20:08:15 +00:00
Brian Paul
f14790d7b0 tweak to render-to-texture region code 2006-03-23 20:05:33 +00:00
Brian Paul
8fb2e61801 In intelCopyBuffer() use current context, not dPriv->driContextPriv->driverPrivate.
The later can lead to nested locking attempt with threaded apps.
2006-03-23 20:03:57 +00:00
Brian Paul
b3c94f9d9d move prevLockFile/Line into context struct 2006-03-23 20:02:57 +00:00
Brian Paul
5b889f7f2d INTEL_PACKCOLOR() no longer needed 2006-03-23 18:58:48 +00:00
Brian Paul
0f531b5b48 Combine the bodies of _mesa_FramebufferTexture1D/2D/3DEXT into a single
function.
2006-03-23 18:25:52 +00:00
Brian Paul
c6482c0d41 Comment about removing screen->fbFormat field in the future. 2006-03-23 02:02:34 +00:00
Brian Paul
b71748efd1 In intelClearColor() always compute both 16bpp and 32bpp clear values
since we won't know which is needed until we're in glClear.
2006-03-23 02:00:45 +00:00
Brian Paul
1c4b9edc41 Initial attempt at software fallback for rendering to a hardware texture
when the texture format isn't supported by the hw rendering system.
Doesn't work yet.
2006-03-23 01:13:43 +00:00
Brian Paul
2b464d93d1 Before calling intel_region_release/reference() check if the regions
are changing.
2006-03-23 01:12:24 +00:00
Brian Paul
497f80ac34 Only try to validate depth/stencil pairing for user-created FBOs.
Disable the intel_region_release/reference() code in intel_draw_buffer()
since it seems redundant with same thing in i915_state_draw_region().
2006-03-23 01:11:29 +00:00
Brian Paul
2be748769b assert(refcount > 0) in intel_region_release() - helpful for finding refernces to free'd memory 2006-03-23 01:03:35 +00:00
Brian Paul
45a1083ee7 use intel_region_reference() in MakeCurrent to make sure we don't accidentally lose the screen->front/back/depth regions 2006-03-23 01:00:49 +00:00
Brian Paul
3a45baa70d fix 16bpp bug 2006-03-22 23:53:07 +00:00
Brian Paul
0bc3a7ac2e fix a test in intel_validate_paired_depth_stencil(), fixes a 16bpp bug 2006-03-22 23:52:18 +00:00
Brian Paul
08f0579176 Rendering to FBO w/ stencil but w/out depth works now.
Assorted clean-ups and fixes.
2006-03-22 23:05:25 +00:00
Brian Paul
d689cd0715 need to resize the depth/stencil wrappers, if present, in _mesa_resize_framebuffer() 2006-03-22 22:05:26 +00:00
Brian Paul
e957f39f67 need an AllocStorage function for resizes 2006-03-22 22:04:32 +00:00
Brian Paul
416f09d3e6 Merge from trunk (get RENDER_START, clip code movement) 2006-03-22 22:03:31 +00:00
Brian Paul
40cc5d36fd assertion fixes 2006-03-22 19:18:04 +00:00
Brian Paul
62f9613dbc remove some invalid assertions (storage may not yet be allocated for the renderbuffer) 2006-03-22 19:16:11 +00:00
Brian Paul
7f31255eb2 Support for separate depth and stencil renderbuffers.
If the user creates several stencil renderbuffers and several depth
renderbuffers, any combination can get bound to a framebuffer object.
Since the hardware only supports combined depth+stencil buffers we
need to do some shuffling of buffer data to make things work.
This code deals with that.
Now fbotexture.c runs in hardware without the -ds flag.
Probably quite a few loose ends, clean-ups remain...
2006-03-22 18:46:18 +00:00
Brian Paul
78382b4bbe Fix a number of issues in the _mesa_extract/insert_stencil() functions.
Pass an attachment index to _mesa_update_depth/stencil_buffer() funcs to
facilitate "paired" depth/stencil renderbuffers in drivers.
New update_color_draw_buffers() and update_color_read_buffer() functions
to make the _mesa_update_framebuffer() function a little cleaner.
2006-03-22 18:40:06 +00:00
Brian Paul
bd8e90857c Call check_begin/end_render_texture() whenever the framebuffer binding
changes in _mesa_BindFramebufferEXT().
2006-03-22 16:48:14 +00:00
Brian Paul
b7cc448ff8 minor clean-up 2006-03-22 16:42:12 +00:00
Brian Paul
0ea582acbe remove unused var 2006-03-22 15:20:58 +00:00
Brian Paul
05c824db87 fix some _ActualFormat initializations 2006-03-22 14:19:17 +00:00
Thomas Hellström
829f6909bd Disable texture memory initialization.
Add some missing error checks in the buffer manager.
2006-03-22 13:24:01 +00:00
Brian Paul
34f1ebc72f New functions for manipulating depth/stencil renderbuffers:
_mesa_extract_stencil(), _mesa_insert_stencil(), _mesa_promote_stencil().
2006-03-22 02:11:28 +00:00
Brian Paul
c6e586ee0c Export _mesa_lookup_renderbuffer() and _mesa_lookup_framebuffer() functions.
Use new _mesa_lookup_texture() function.
2006-03-22 02:10:09 +00:00
Brian Paul
9180d932c6 New _mesa_lookup_texture() function to wrap the hashtable lookup. 2006-03-22 02:09:22 +00:00
Brian Paul
95df1b67a2 Reorganize the code relating to updating the framebuffer's _DepthBuffer
and _StencilBuffer fields.
These fields are often wrappers/adaptors around combined depth/stencil
renderbuffers.
Make _mesa_update_depth_buffer() and _mesa_update_stencil_buffer() public.
2006-03-22 02:08:30 +00:00
Brian Paul
bc400c3f30 Lots of updates for new gl_renderbuffer ClassID and _ActualFormat fields.
Removed hw_stencil field from context.  Now determine hw stencil from looking
at the stencil renderbuffer.
Enabled the GL_EXT_packed_depth_stencil extension.  May not be permanent but
for now it allows hw stencil to work with the fbotexture.c demo (w/ -ds flag).
Using separate renderbuffers for GL_DEPTH_ATTACHMENT_EXT and
GL_STENCIL_ATTACHMENT_EXT works, but is currently a software fallback.
2006-03-21 23:58:03 +00:00
Brian Paul
3a3db0e9ec A number of renderbuffer changes:
1. Added _ActualFormat field to record the actual storage format chosen by
   Mesa or the driver.  The InternalFormat field has to store the value that
   the user passed into the glRenderbufferStorageEXT() function.
2. Added ClassID field so driver can distinguish between gl_renderbuffers
   and intel_renderbuffers (for example).  Not very OOP-like, but seems to
   be a reasonable solution.
2006-03-21 23:53:06 +00:00
Brian Paul
613e395ab8 added -DDEBUG so core mesa debug/ASSERT code is activated (temporary on this branch) 2006-03-21 23:18:46 +00:00
Brian Paul
86c5de8b85 fix token in assertion 2006-03-21 23:17:37 +00:00
Brian Paul
44c8c42ab9 GL_EXT_packed_depth_stencil should be off by default 2006-03-21 21:56:04 +00:00
Brian Paul
31a82a663c When s/w rendering to texture memory, don't invert Y as for regular rendering.
Perhaps put yScale, yBias factors into intel_renderbuffer since they're
the same as those in intelCalcViewport().
2006-03-21 21:39:21 +00:00
Keith Whitwell
dafdf6512e Use 64 byte-aligned pitches for RBO's 2006-03-21 20:30:10 +00:00
Keith Whitwell
9caacb015a Add a few assertions, currently hit by fgl_glxgears 2006-03-21 20:02:37 +00:00
Keith Whitwell
2887770534 Protect depth buffer emit with test for state->depth_region 2006-03-21 18:42:22 +00:00
Brian Paul
fb440c9f82 Need to set hardware viewport params depending on window vs. FBO rendering
and normal FBO vs. RTT.  Fixes upside down teapot in fbotexture.c demo.
Still need to adjust glDraw/Read/CopyPixels Y direction depending on if
we're doing RTT.
2006-03-21 18:35:02 +00:00
Brian Paul
576c9c310f comments, #if 0 / #endif some apparently unused context fields 2006-03-21 16:55:42 +00:00
Brian Paul
ec1db9db1f In intelReadBuffer() check/update framebuffer completeness.
Added intel_get_renderbuffer() and intel_get_rb_region() helper functions
to simplify some code (should be inlined in the future).
2006-03-21 16:46:05 +00:00
Brian Paul
e1f70cf5e2 include intel_buffers.h 2006-03-21 01:11:41 +00:00
Brian Paul
a7cdbf5c38 Additional login in intel_draw_buffer() to check if any needed renderbuffers
are software/fallback cases.
The hardware's combined depth/stencil buffer is now treated as such
(ala GL_EXT_packed_depth_stencil).  So the depth/stencil span functions
are effectively merged.  Renderbuffers wrappers will extract the depth or
stencil values when needed.
2006-03-21 01:11:12 +00:00
Brian Paul
fe37adfde3 Added _mesa_finish_render_texture() function and reference counting for
the renderbuffer which wraps textures.
2006-03-21 00:47:40 +00:00
Brian Paul
315396ac6c Created new intel_buffers.h file with appropriate prototypes.
Moved body of intelDrawBuffer() into new intel_draw_buffer() which will do
additional things in future.
2006-03-20 23:53:29 +00:00
Brian Paul
a7252f42ae use correct renderbuffer regions in intelClearWithTris() 2006-03-20 23:37:54 +00:00
Brian Paul
bffc66109e fix up some loose ends for render to texture, clean-ups 2006-03-20 23:35:02 +00:00
Brian Paul
0089c7f4ee Checkpoint: render-to-texture starting to work. Had to turn off stencil
in fbotexture.c.  Teapot is drawn upside down, not centered...
2006-03-20 22:12:48 +00:00
Brian Paul
54f435340b debug code to enable/disable depth/stencil operations 2006-03-20 22:09:58 +00:00
Brian Paul
66d887d605 Checkpoint render-to-texture. Doesn't function, but doesn't crash either. 2006-03-20 21:08:55 +00:00
Brian Paul
c6dc5cc8ab update get_teximage_source() to use renderbuffer regions 2006-03-20 19:02:37 +00:00
Brian Paul
e0412bb726 updates to sync with trunk merge 2006-03-20 19:01:10 +00:00
Brian Paul
cc5cbd1bca Merge from CVS trunk (get render-to-texture updates). 2006-03-20 19:00:18 +00:00
Keith Whitwell
93fbfa5781 Use an rgba image so that hw pbos work. 2006-03-20 18:54:54 +00:00
Keith Whitwell
30709caad6 Restore animation 2006-03-20 18:54:22 +00:00
Keith Whitwell
a647198f65 Remove old DRM_SOURCE_PATH defn 2006-03-20 18:54:06 +00:00
Keith Whitwell
7ad6ea6ff2 Call _mesa_update_state() before checking FragmentProgram->_Enabled 2006-03-20 18:52:56 +00:00
Brian Paul
ceee2c45cd Fixed bug in intelClearWithBlit(). If clearing multiple cliprects, the
buffer mask was clobbered after the first rect.
Rename 'flags' to 'mask' to be consistent w/ other clearing code.
2006-03-20 16:06:07 +00:00
Brian Paul
26dc161fde XXX comments 2006-03-20 15:50:59 +00:00
Brian Paul
b176ef05f2 In intelCopyBuffer(), use renderbuffer regions instead of context's region
pointers.  Added const qualifiers.  Added comments.
2006-03-20 15:50:09 +00:00
Brian Paul
6d6e7a08c7 Fix up intelSwapBuffers:
- get gl_framebuffer pointer from dPriv.
 - flush current context if bound to window we're swapping.  Previous code
   could try to flush a non-current context.
2006-03-20 15:48:12 +00:00
Brian Paul
eb75ec2349 merge from trunk (additional renderbuffer error checks, debug code) 2006-03-20 15:39:30 +00:00
Brian Paul
2a8bd4e329 Replace intel_clip_to_framebuffer(), intel_clip_to_drawable(), and
intel_clip_to_region() with new _mesa_clip_to_region().
2006-03-20 02:23:26 +00:00
Brian Paul
c247268499 added _mesa_clip_to_region() 2006-03-20 02:17:15 +00:00
Brian Paul
b2cb8920c2 FBO test - teapot 2006-03-19 19:07:44 +00:00
Brian Paul
af4d93f256 Fix some issues with depth renderbuffers. 3D rendering into FBOs seems OK now.
Misc clean-ups in other places.
2006-03-19 19:06:12 +00:00
Brian Paul
c8dd839acb remove debug code 2006-03-19 19:04:12 +00:00
Brian Paul
e43c3c38fb simplify intelClearWithTris() for renderbuffers 2006-03-19 17:08:00 +00:00
Brian Paul
9194782fdc Merge i915_set_draw_region() and i915 meta_draw_region() into new i915_state_draw_region(). 2006-03-19 16:50:59 +00:00
Brian Paul
ec36d5b537 undo a debugging hack 2006-03-19 16:50:08 +00:00
Brian Paul
6e5da1a860 intelClearWithTriangles now handles FBOs.
Had to fix up i915 meta_draw_region() function.
Try to combine some duplicated code in next check-in.
2006-03-19 16:39:56 +00:00
Brian Paul
21f6e8a2d0 added BUFFER_BITS_COLOR 2006-03-19 16:38:39 +00:00
Brian Paul
18772c9e88 sync with trunk (GL_READ/DRAW_BUFFER queries) 2006-03-19 00:11:29 +00:00
Brian Paul
5df4283b53 FBO Checkpoint:
Basic FBO hardware rendering now working (fbotest1.c works at least).
2006-03-19 00:05:55 +00:00
Brian Paul
6734bab3b2 Checkpoint FBO work:
The progs/tests/fbotest1.c demo works (yeah!), with some caveats:
 - Only glClear is done in hardware, actually rendering is sw fallback now.
 - Initial expose/draw is broken, works on subsequent draws.
Lots of changes in fallback/span code for FB objects.
Almost full rewrite of intelClearWithBlit() for renderbuffers.
Total rewrite of intelDrawBuffer() function.
Add FBO support to intelClearWithTris() but is currently broken.
Temporary hack in MakeCurrent():
 - since we can't create the screen/static renderbuffer regions in
   intelCreateBuffer() like we should (no current context with which to lock),
   init the renderbuffer's regions in MakeCurrent by copying from
   intel->front/back/depth_region.
Still using old DRI front/back/depth mappings for sw rendering to windows.
When those mappings go away, we'll use the new renderbuffer region mappings.
2006-03-18 21:55:34 +00:00
Brian Paul
0a5fea5f96 Don't call Driver->Bitmap() if no image to render 2006-03-18 21:46:02 +00:00
Brian Paul
9b2762d7b9 Call _mesa_resize_framebuffer() in intelWindowMoved() to update Mesa's
notion of window size.
Remove unnecessary ctx->Driver.DepthRange() call from intelWindowMoved().
2006-03-17 22:06:59 +00:00
Brian Paul
571bf7a71b Change loops from firstLevel to lastLevel to be inclusive of lastLevel
(i.e. change < to <=).  Otherwise, 0th image of non-mipmapped textures
wasn't getting mapped and software rendering died.
2006-03-17 20:44:09 +00:00
Brian Paul
4ab3b9aa76 Implement glGetTexImage.
In intel_tex_map_images(), convert strides from bytes to texels for Mesa.
Store the 3D ImageStride now added to core Mesa.
2006-03-17 18:17:19 +00:00
Brian Paul
88c018ee47 remove some const qualifiers since we may need to modify fields for mapping 2006-03-17 18:11:37 +00:00
Brian Paul
cead52ef68 added ImageStride field to gl_texture_image 2006-03-17 18:11:09 +00:00
Thomas Hellström
9cf0ed6059 Verbose error reporting.
Run indent on intel_bufmgr.c
2006-03-17 15:33:26 +00:00
Thomas Hellström
2c1c8dccf7 Clean up flag handling. 2006-03-17 13:54:38 +00:00
Brian Paul
b87f9f6056 thread safety fixes from trunk 2006-03-15 21:02:52 +00:00
Brian Paul
427bf0171d update assertion 2006-03-15 20:20:32 +00:00
Brian Paul
98c5445c75 make soft_renderbuffer_storage() into public _mesa_soft_renderbuffer_storage() 2006-03-15 19:42:48 +00:00
Brian Paul
15ffb3bbab checkpoint 2006-03-15 17:52:15 +00:00
Brian Paul
97b570b999 just check-point some FBO code 2006-03-15 17:51:27 +00:00
Brian Paul
e8e6374a16 New code for setting cliprects when rendering to a FBO. 2006-03-15 17:50:40 +00:00
Brian Paul
d9f31f16c0 sync with trunk 2006-03-15 17:47:05 +00:00
Brian Paul
1173198f51 added GL_EXT_framebuffer_blit from trunk 2006-03-15 17:37:52 +00:00
Brian Paul
01a56d23e6 fix more assertions that wrap essential code (-DNDEBUG case) 2006-03-15 00:25:47 +00:00
Brian Paul
bf050799ac new intel_renderbuffer struct 2006-03-15 00:17:57 +00:00
Brian Paul
3697eca493 new intel_map_unmap_buffers() routine which will eventually be used to map or unmap all renderbuffers which we may need during software rendering 2006-03-15 00:17:22 +00:00
Brian Paul
de2b3506ea allow format = GL_RGB5, GL_RGBA8 2006-03-14 23:36:52 +00:00
Brian Paul
bfbe2eb6e9 new intel_set_span_functions(), bridge to new code 2006-03-14 23:36:10 +00:00
Brian Paul
8bd395f601 comments 2006-03-14 23:34:37 +00:00
Brian Paul
735925d15b include intel_fbo 2006-03-14 23:34:12 +00:00
Brian Paul
448a3456a9 Added BindFramebuffer() driver hook.
Rename base_internal_format() to _mesa_base_fbo_format() and make public.
2006-03-14 22:43:01 +00:00
Brian Paul
e176b11b74 init Red/Green/EtcBits = 0 in soft_renderbuffer_storage() 2006-03-14 22:40:56 +00:00
Brian Paul
cdc8771893 added some assertions as prep to removing use of dPriv fields. new comments. 2006-03-14 21:56:26 +00:00
Brian Paul
789399d3f4 Replace code like this:
assert(!drmFoobar());
with:
	int k = drmFoobar();
	assert(!k);
so that the drm calls don't disappear if we compile with NDEBUG!
2006-03-14 21:53:33 +00:00
Brian Paul
dfa8624e83 just comments, doxygen 2006-03-14 19:19:12 +00:00
Brian Paul
36b64bbd4f initial skeletons for GL_EXT_framebuffer_object 2006-03-14 19:17:09 +00:00
Keith Whitwell
651985f813 Clear optimizations.
- Correct comparison of stencil writemask with 0xff.
	- Do depth with triangles if we are already doing stencil that way.
2006-03-13 18:53:01 +00:00
Keith Whitwell
9f2b49a7b3 Turn the render stage back on. 2006-03-13 18:51:00 +00:00
Keith Whitwell
05c6361b0b reinstate old unlock + sched_yeild behaviour when nr_cliprects == 0 2006-03-13 16:41:45 +00:00
Keith Whitwell
9621817253 drmOpen/Close hacks to coalesce multiple drm opens 2006-03-13 16:26:50 +00:00
Keith Whitwell
7e2e4a6b1a Use drmCloseOnce() 2006-03-13 16:23:37 +00:00
Keith Whitwell
656c71ca3f Check to see if a bufmgr has already been created for the current drm
fd.  If so reuse it.

Also, add _glthread_Mutex guards around (some of the) potential
thread-unsafe code.
2006-03-13 16:22:59 +00:00
Thomas Hellström
6ce7055dcc Remove wait for fence at the end of intelFlush. 2006-03-07 11:07:23 +00:00
Keith Whitwell
c848a65b5e Use braces around size parameter in BEGIN_BATCH. Hopefully fixes
batch overrun problems.
2006-03-06 18:10:27 +00:00
Thomas Hellström
1ff99fcd50 New libdrm flag numbers. 2006-03-06 13:50:40 +00:00
Keith Whitwell
67342052d2 Add copypix.c demo.
Add PBO version of drawpix.c demo.
2006-03-06 13:31:18 +00:00
Thomas Hellström
ccf52b6784 Move over to libdrm.
At least one lockup remaining with multiple clients when at least one client
is using textures.
2006-03-05 21:52:03 +00:00
Thomas Hellström
78aa58c914 Add bufmgr_old that keeps the old pre-ttm functionality.
Modify bufmgr_fake.c for new drm interface. Full rework for bufmgr.c pending.
2006-03-03 18:13:19 +00:00
Thomas Hellström
4291f24abd Add a define NO_TTM to disable ttm usage altogether for comparison.
Reinstate MI_FLUSH at end of batchbuffers.
2006-03-02 11:41:28 +00:00
Keith Whitwell
f4211722f1 Get texture drawpixels working 2006-03-01 18:07:06 +00:00
Keith Whitwell
71380a1325 Get basic texturing and stencil working 2006-03-01 16:49:11 +00:00
Keith Whitwell
33e55c6a7d i830 driver first triangles (with a faked out bufmgr) 2006-03-01 16:06:47 +00:00
Keith Whitwell
cd32164cc6 Port the i830 driver to the texture manager. Compiles but not tested.
Turn back on some fallback cases.
Turn back on the unclipped rastersetup-to-dma render path.
2006-03-01 00:06:14 +00:00
Keith Whitwell
7c1348ac8f Remove the flags argument for intel_meta_draw_quad(). 3D primitives
must always be emitted with cliprects else the drawing origin may not
be emitted either.
2006-02-27 17:38:56 +00:00
Thomas Hellström
2560061cfe Silence printout and nicer wait for IRQ when out of batchbuffer mem. 2006-02-27 16:50:17 +00:00
Keith Whitwell
0c047b8847 Texture copypixels, fixes to blit path also.
Need to add logic to avoid using texture engine where source, dest overlap.
2006-02-27 16:39:41 +00:00
Thomas Hellström
c64a08c286 Call kernel to update the sarea breadcrumb when we seem to be out of
batchbuffer memory.

Remove flushes from batchbuffer tails. They are not needed anymore
when we have the kernel sync flush mechanism.

Better kernel error checks.
2006-02-27 16:28:10 +00:00
Keith Whitwell
bb409e88d8 Fix drawpixels window coordinate calculation.
Make sure cliprects are emitted for metaops texture quads.
Implement PixelZoom for drawpixels.
2006-02-27 13:51:10 +00:00
Keith Whitwell
af69eefcba Fix logic for calculating regions for partial-buffer clears. 2006-02-27 13:18:13 +00:00
Keith Whitwell
d9c071adec - Use a raw buffer id rather than an intel_region struct for texture
state/relocations.
- Implement basic texture engine drawpixels.
2006-02-26 16:47:15 +00:00
Keith Whitwell
833d19c21d Make this struct less opaque. 2006-02-26 14:39:23 +00:00
Keith Whitwell
7245757174 Use spantmp2.h, based on r200 driver. 2006-02-26 14:37:54 +00:00
Keith Whitwell
3d96cb7d48 First pass at using the texture engine for copypixels. Currently only
does the same operations as are accelerated by the blitter, though this
will change...
2006-02-26 14:37:30 +00:00
Keith Whitwell
f565ab2dd5 For some reason, streaming copies to write-combined regions are
extremely sensitive to the characteristics of how the source data is
retrieved.  By reordering the source reads in the rgba to bgra
conversion, the speed of this operation increases by half.
2006-02-26 12:46:51 +00:00
Thomas Hellström
7ad0c51f48 Enable uncached TTMs by default.
Allocate batchbuffers from a 1MB local TTM pool =>
multiple clients.
2006-02-26 04:29:28 +00:00
Keith Whitwell
fea684c533 fix misleading MI_FLUSH defn and usage 2006-02-25 18:57:43 +00:00
Keith Whitwell
4e8845fc0c a few missed cases where blits can't do read/drawpixels 2006-02-25 15:33:48 +00:00
Keith Whitwell
ffcc1cdb41 Tweak the read format/type slightly so this can use the blitter. 2006-02-24 17:51:04 +00:00
Keith Whitwell
afc90075ba get PBO readpixels working also 2006-02-24 17:23:57 +00:00
Keith Whitwell
79acea2708 Get PBO drawpixels working. 2006-02-24 16:52:47 +00:00
Keith Whitwell
a12063a540 use expected argument order for intel_check_blit_format 2006-02-24 16:52:06 +00:00
Keith Whitwell
9826d83439 Add missing GetSubData callback.
Fill in various parts of the base gl_buffer_object struct as required from
each of our callbacks.
2006-02-24 16:51:33 +00:00
Keith Whitwell
84f7ded925 add bmBufferGetSubData 2006-02-24 16:50:22 +00:00
Keith Whitwell
59dd8ad752 Hack bmBufferData and bmBufferSubdata back into operation with an
implicit map/unmap.
2006-02-24 15:02:41 +00:00
Keith Whitwell
4afd26982e Hook up buffer_objects implementation to DrawPixels for testing.
Not yet working.
2006-02-24 13:58:45 +00:00
Keith Whitwell
17e4a7ea17 Bring DBG_BM() macros back to DBG(). Turn on by setting
INTEL_DEBUG=buf in the environment.
2006-02-24 13:56:28 +00:00
Keith Whitwell
3d67655cce bufferobjects implementation layered on top of bm buffers 2006-02-24 11:56:45 +00:00
Keith Whitwell
b5d7c69884 Define union fi, reenable clear-with-tris. 2006-02-24 11:05:35 +00:00
Keith Whitwell
b6759e2be7 Add an assert 2006-02-24 10:10:50 +00:00
Keith Whitwell
af853b0da7 Flush old primitive before starting new one in intelRasterPrimitive. 2006-02-24 10:10:28 +00:00
Keith Whitwell
8d349798da Add a callback to set post-fragment state in the metaops utility.
Useful for accelerating read/draw/copy pixels when blitting isn't
sufficient.
2006-02-23 14:24:39 +00:00
Keith Whitwell
4aea628194 Fix clipping for copypixel 2006-02-23 14:23:50 +00:00
Keith Whitwell
008ddf628a Remove dead code 2006-02-23 14:23:06 +00:00
Thomas Hellström
716496f263 Hack bufmgr_fake to allocate from ttms when possible. 2006-02-23 13:30:11 +00:00
Keith Whitwell
b3b325e560 get 3d textures working again 2006-02-23 11:47:36 +00:00
Keith Whitwell
382ce985ac Fix cubemap layout 2006-02-22 19:54:32 +00:00
Keith Whitwell
54b7eca7a0 Append an MI_FLUSH to each batchbuffer for synchronization. Not really
ideal from a performance viewpoint and there are mechanisms to avoid this
in future.
2006-02-22 19:26:37 +00:00
Keith Whitwell
f74e06bf11 restore swapbuffers throttling 2006-02-22 17:18:19 +00:00
Keith Whitwell
9c02649d18 Introduce fixup/relocation lists for dma buffers. 2006-02-22 15:16:01 +00:00
Keith Whitwell
2c34704e41 tweaks 2006-02-13 00:41:33 +00:00
Keith Whitwell
85d0041ff0 rename texdown to reflect behaviour changes 2006-02-13 00:40:33 +00:00
Keith Whitwell
67ff8b354e bump driver date, etc 2006-02-13 00:39:20 +00:00
Keith Whitwell
08e7957571 Fix inverted image in copytexsubimage by tickling the hardware to
do the inversion in the blitter.
2006-02-13 00:38:46 +00:00
Keith Whitwell
9c1f7089d8 Some functions had been indented by one space?! 2006-02-11 04:28:13 +00:00
Keith Whitwell
5381ac5f11 move blit functions to new file 2006-02-11 02:54:09 +00:00
Keith Whitwell
a6f78d4eee Use aligned malloc for backing store, if necessary. 2006-02-10 00:01:45 +00:00
Keith Whitwell
ae695e3566 Remove 2nd copy of do_memcpy 2006-02-09 23:09:47 +00:00
Keith Whitwell
c82c3335e1 fix refcounting and other issues 2006-02-09 23:06:23 +00:00
Keith Whitwell
f8246f504b Add basic timing for memcpys 2006-02-09 23:04:44 +00:00
Keith Whitwell
499458bcdb Add INVARIENT to the active state list 2006-02-09 23:01:34 +00:00
Keith Whitwell
37a53fd6a0 Make various changes to get a number out of texdown that better
represents realworld usage.  In particular, avoid situations where
the client texture image and the mesa copy (if there is one) are both
resident in L2 cache.
2006-02-09 22:52:20 +00:00
Keith Whitwell
5ec38fb2ea Turn DBG output on/off with INTEL_DEBUG=bufs 2006-02-09 22:21:20 +00:00
Keith Whitwell
11c0215bf8 Switch between memcpy implementations according to src/dest alignment. 2006-02-01 18:42:16 +00:00
Keith Whitwell
6a13b6c346 Debug off 2006-02-01 18:30:16 +00:00
Keith Whitwell
a103097ee5 Quieten depend 2006-02-01 18:29:56 +00:00
Keith Whitwell
7efad0d84c Just build the i915 on this branch 2006-02-01 18:29:25 +00:00
Keith Whitwell
42c88cd072 subtexrate test on this branch too 2006-02-01 18:14:09 +00:00
Keith Whitwell
2541c54e79 gearbox demo on this branch too 2006-02-01 18:13:23 +00:00
Keith Whitwell
33529e3d8e Bump driver date 2006-02-01 18:01:04 +00:00
Keith Whitwell
84c1b82081 Disable check_copytex_fragment_ops - it doesn't really apply. 2006-02-01 16:40:23 +00:00
Keith Whitwell
a97a1439ae Get batchbuffers working natively again. This code still
relies over-heavily on the DRI lock to protect offsets in the
command stream from changing before being queued on the ring,
and should be viewed as being a pretty temporary mechanism
before a more robust alternative is implemented, most likely
based on a batchbuffer relocation list that will be used
to patch prebuilt batchbuffers after validation takes place.
2006-02-01 15:54:42 +00:00
Keith Whitwell
2fd2910010 Remove the last of the old AllocateAgp mechanism.
Move the batchbuffer code to being effectively a ring of
bufmgr buffers.
2006-02-01 15:51:31 +00:00
Keith Whitwell
fbbda155e0 Add code to map/unmap all texture images for the software rasterizer.
Add the color and depth buffers to the validation list to ensure they
are fenced correctly by hardware rasterization.
2006-02-01 15:50:14 +00:00
Keith Whitwell
a49c3c0fae Ensure that color buffers and textures are mapped (bmBufferMap) before
software rasterizer fallbacks.  This has two functions, firstly to
ensure that the Data pointers point to something and secondly to
ensure than any pending fences on those buffers are discharged before
allowing the software rasterizer to read/write the data.

This needs to be integrated with Brian's validate code.
2006-02-01 15:48:52 +00:00
Keith Whitwell
baf5998d59 file gearbox.c was added on branch texman_0_1_branch on 2006-02-01 18:13:23 +0000 2006-01-30 15:35:35 +00:00
Keith Whitwell
4c5acef241 Get hardware-accelerated CopyTexSubImage working well enough to run
Brian's gearbox demo.
2006-01-28 23:28:14 +00:00
Keith Whitwell
9839e272cf Allow ValidateBuffers to allocate memory for buffers which haven't yet
got it by other methods.  Typically this is buffers being written to by
hardware excluding the fixed front/back/depth buffers which are have
pre-allocated memory.

At some point will want to pass BM_READ/BM_WRITE flags to catch the
couple of cases where buffers are treated differently in each case.
2006-01-28 23:27:39 +00:00
Keith Whitwell
b57e79ff14 remove debug 2006-01-28 17:52:50 +00:00
Keith Whitwell
43824acb4e Build fixes 2006-01-28 17:52:05 +00:00
Keith Whitwell
d8f509e749 Use the x86 __memcpy to avoid performance clif for uploads where the
source data is worse than 64-byte aligned.
2006-01-28 17:50:59 +00:00
Keith Whitwell
eb91c93c2e file subtexrate.c was added on branch texman_0_1_branch on 2006-02-01 18:14:09 +0000 2006-01-27 15:44:40 +00:00
Keith Whitwell
79de983b6f initial copytexsubimage code, untested 2006-01-27 11:58:00 +00:00
Brian Paul
fdb3acf016 added _swrast_eject_texture_images() 2006-01-27 03:42:56 +00:00
Keith Whitwell
2807d1f58a Get readbuffer correctly. 2006-01-26 18:30:34 +00:00
Keith Whitwell
93f913926e - Remove (most of) old agp client memory hack.
- Implement an accelerated version of glCopyPixels using the blitter.
2006-01-26 17:21:38 +00:00
Keith Whitwell
33ca04f379 Expand the buffer manager to include a notion of multiple pools within
a memory space.  Allow some pools to be excluded from the upload/evict
processing, meaning that any buffers within those pools are effectively
fixed.  Add a mechanism to create buffers in those pools.

This allows the legacy fixed front/depth/back buffers to be represented
in this scheme and will allow other future pinned buffers to be allocated
from fixed pools in such a way that they cannot fragment the rest of
the texture memory.
2006-01-26 14:50:02 +00:00
Brian Paul
398cb30c72 Added _swrast_validate_texture_images() to make sure all textures have
data resident for software rasterization.
Relies on new swrast driver function: ValidateTextureImage()
2006-01-26 04:05:53 +00:00
Keith Whitwell
f67bb30314 Fix confusion over pitch. demos/texobj renders correctly. 2006-01-25 17:16:46 +00:00
Keith Whitwell
4578d7b9f0 Offset returns weren't being returned. 2006-01-25 16:57:36 +00:00
Keith Whitwell
dcdfc154c3 Remove silly debug. 2006-01-25 16:46:10 +00:00
Keith Whitwell
696ba32779 Another texture manager checkpoint:
- Add code to validate textures before use.
- Simplify vertex paths for now.
- Make vertex paths validate textures.  This is done pretty
  with some pretty heavy-handed use of the dri lock - fixing this is
  a priority.
- Add lots of debug statements

demos/texobj renders, but textures are incorrect.
2006-01-25 15:40:50 +00:00
Keith Whitwell
dcfe55539f Remove dead code. Gears runs. 2006-01-24 18:55:52 +00:00
Keith Whitwell
ff84b1f1b2 Checkpoint of texture manager rework for i915.
Compiles but won't do any more than that.
2006-01-24 18:35:53 +00:00
Keith Whitwell
3bca9c47f4 Add another layer on top of the simple 2d regions in intel_regions.[ch]
which keeps track of a whole, well-defined mipmap tree.  These are a
fixed layout on intel hardware and managing them is complicated in the
face of GL's TexImage function calls where data can arrive in any order,
making it difficult to guess a layout ahead of time.

Wrapping mipmap trees up in a struct and programming interface like this
reduces the burden elsewhere.
2006-01-24 16:38:43 +00:00
Keith Whitwell
d4d7fdb43b layer 2d region semantics and blits on top of bufmgr buffers 2006-01-23 12:53:11 +00:00
Keith Whitwell
d65dab5777 import via texture semantics 2006-01-23 12:52:28 +00:00
Keith Whitwell
638ca019ef Add a faked-out implementation of the buffer manager that uses the same
techniques as the old dri memory manager behind the new interface.  Will
use this to port the i915 driver to this interface to hopefully get
some easy insights from using the interface.
2006-01-16 15:30:45 +00:00
231 changed files with 35082 additions and 20872 deletions

View File

@@ -10,9 +10,6 @@ MESA_MAJOR=6
MESA_MINOR=5
MESA_TINY=0
# external projects. This should be useless now that we use libdrm.
DRM_SOURCE_PATH=$(TOP)/../drm
# Compiler and flags
CC = cc
CXX = CC

View File

@@ -9,11 +9,12 @@ CONFIG_NAME = linux-dri
CC = gcc
CXX = g++
MKDEP = /usr/X11R6/bin/makedepend
#MKDEP = /usr/X11R6/bin/makedepend
#MKDEP = gcc -M
#MKDEP_OPTIONS = -MF depend
OPT_FLAGS = -g
#OPT_FLAGS = -g -march=pentium4 -fprefetch-loop-arrays
OPT_FLAGS = -O2
PIC_FLAGS = -fPIC
# Add '-DGLX_USE_TLS' to ARCH_FLAGS to enable TLS support.
@@ -22,6 +23,7 @@ ARCH_FLAGS ?=
DEFINES = -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE \
-D_BSD_SOURCE -D_GNU_SOURCE \
-DPTHREADS -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER \
-DDEBUG \
-DGLX_DIRECT_RENDERING -DHAVE_ALIAS
X11_INCLUDES = -I/usr/X11R6/include
@@ -63,5 +65,7 @@ WINDOW_SYSTEM=dri
# gamma are missing because they have not been converted to use the new
# interface.
DRI_DIRS = i810 i830 i915 mach64 mga r128 r200 r300 radeon s3v \
DRI_DIRS = i915 mach64 mga r128 r200 r300 radeon s3v \
savage sis tdfx trident unichrome ffb
DRI_DIRS = i915

View File

@@ -2260,6 +2260,28 @@ typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pnam
#ifndef GL_EXT_framebuffer_blit
#define GL_EXT_framebuffer_blit 1
#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
GLAPI void GLAPIENTRY
glBlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC)
(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
#endif /* GL_EXT_framebuffer_blit */
#ifndef GL_EXT_packed_depth_stencil
#define GL_EXT_packed_depth_stencil 1

View File

@@ -20,11 +20,14 @@ PROGS = \
clearspd \
cubemap \
drawpix \
copypix \
drawpix_pbo \
fire \
fogcoord \
fplight \
gamma \
gears \
gearbox \
geartrain \
glinfo \
gloss \
@@ -51,7 +54,7 @@ PROGS = \
terrain \
tessdemo \
texcyl \
texdown \
texdown-pool \
texenv \
texobj \
trispd \
@@ -73,9 +76,8 @@ PROGS = \
##### TARGETS #####
default: $(PROGS)
default: readtex.o $(PROGS)
$(PROGS): readtex.o
readtex.c: $(TOP)/progs/util/readtex.c
cp $< .

364
progs/demos/copypix.c Normal file
View File

@@ -0,0 +1,364 @@
/*
* glDrawPixels demo/test/benchmark
*
* Brian Paul September 25, 1997 This file is in the public domain.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <GL/glut.h>
#include "readtex.h"
#define IMAGE_FILE "../images/girl.rgb"
static int ImgWidth, ImgHeight;
static GLenum ImgFormat;
static GLubyte *Image = NULL;
static int Xpos, Ypos;
static int SkipPixels, SkipRows;
static int DrawWidth, DrawHeight;
static int Scissor = 0;
static int Fog = 0;
static GLfloat Zpos = -1.0;
static float Xzoom, Yzoom;
static GLboolean DrawFront = GL_FALSE;
static GLboolean Dither = GL_TRUE;
static void Reset( void )
{
Xpos = Ypos = 20;
DrawWidth = ImgWidth;
DrawHeight = ImgHeight;
SkipPixels = SkipRows = 0;
Scissor = 0;
Fog = 0;
Zpos = -1.0;
Xzoom = Yzoom = 1.0;
}
static void Display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
glRasterPos2i(10, 10);
glPixelZoom( 1, 1 );
glDisable(GL_SCISSOR_TEST);
glDisable(GL_FOG);
glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image);
#if 0
glRasterPos2i(Xpos, Ypos);
#else
/* This allows negative raster positions: */
glRasterPos3f(0, 0, Zpos);
glBitmap(0, 0, 0, 0, Xpos, Ypos, NULL);
#endif
glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels);
glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows);
glPixelZoom( Xzoom, Yzoom );
if (Scissor)
glEnable(GL_SCISSOR_TEST);
if (Fog)
glEnable(GL_FOG);
glCopyPixels(10, 10, ImgWidth, ImgHeight, GL_COLOR);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_FOG);
if (DrawFront)
glFinish();
else
glutSwapBuffers();
}
static void Benchmark( void )
{
int startTime, endTime;
int draws = 500;
double seconds, pixelsPerSecond;
printf("Benchmarking...\n");
/* GL set-up */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels);
glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows);
glPixelZoom( Xzoom, Yzoom );
if (Scissor)
glEnable(GL_SCISSOR_TEST);
if (Fog)
glEnable(GL_FOG);
if (DrawFront)
glDrawBuffer(GL_FRONT);
else
glDrawBuffer(GL_BACK);
/* Run timing test */
draws = 0;
startTime = glutGet(GLUT_ELAPSED_TIME);
do {
glCopyPixels(10, 10, ImgWidth, ImgHeight, GL_COLOR);
draws++;
endTime = glutGet(GLUT_ELAPSED_TIME);
} while (endTime - startTime < 4000); /* 4 seconds */
/* GL clean-up */
glDisable(GL_SCISSOR_TEST);
glDisable(GL_FOG);
/* Results */
seconds = (double) (endTime - startTime) / 1000.0;
pixelsPerSecond = draws * DrawWidth * DrawHeight / seconds;
printf("Result: %d draws in %f seconds = %f pixels/sec\n",
draws, seconds, pixelsPerSecond);
}
static void Reshape( int width, int height )
{
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0, width, 0.0, height, 0.0, 2.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glScissor(width/4, height/4, width/2, height/2);
}
static void Key( unsigned char key, int x, int y )
{
(void) x;
(void) y;
switch (key) {
case ' ':
Reset();
break;
case 'd':
Dither = !Dither;
if (Dither)
glEnable(GL_DITHER);
else
glDisable(GL_DITHER);
break;
case 'w':
if (DrawWidth > 0)
DrawWidth--;
break;
case 'W':
DrawWidth++;
break;
case 'h':
if (DrawHeight > 0)
DrawHeight--;
break;
case 'H':
DrawHeight++;
break;
case 'p':
if (SkipPixels > 0)
SkipPixels--;
break;
case 'P':
SkipPixels++;
break;
case 'r':
if (SkipRows > 0)
SkipRows--;
break;
case 'R':
SkipRows++;
break;
case 's':
Scissor = !Scissor;
break;
case 'x':
Xzoom -= 0.1;
break;
case 'X':
Xzoom += 0.1;
break;
case 'y':
Yzoom -= 0.1;
break;
case 'Y':
Yzoom += 0.1;
break;
case 'z':
Zpos -= 0.1;
printf("RasterPos Z = %g\n", Zpos);
break;
case 'Z':
Zpos += 0.1;
printf("RasterPos Z = %g\n", Zpos);
break;
case 'b':
Benchmark();
break;
case 'F':
Fog = !Fog;
printf("Fog %d\n", Fog);
break;
case 'f':
DrawFront = !DrawFront;
if (DrawFront)
glDrawBuffer(GL_FRONT);
else
glDrawBuffer(GL_BACK);
printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK");
break;
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void SpecialKey( int key, int x, int y )
{
(void) x;
(void) y;
switch (key) {
case GLUT_KEY_UP:
Ypos += 1;
break;
case GLUT_KEY_DOWN:
Ypos -= 1;
break;
case GLUT_KEY_LEFT:
Xpos -= 1;
break;
case GLUT_KEY_RIGHT:
Xpos += 1;
break;
}
glutPostRedisplay();
}
static void Init( GLboolean ciMode, const char *filename )
{
static const GLfloat fogColor[4] = {0, 1, 0, 0};
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
Image = LoadRGBImage( filename, &ImgWidth, &ImgHeight, &ImgFormat );
if (!Image) {
printf("Couldn't read %s\n", filename);
exit(0);
}
if (ciMode) {
/* Convert RGB image to grayscale */
GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight );
GLint i;
for (i=0; i<ImgWidth*ImgHeight; i++) {
int gray = Image[i*3] + Image[i*3+1] + Image[i*3+2];
indexImage[i] = gray / 3;
}
free(Image);
Image = indexImage;
ImgFormat = GL_COLOR_INDEX;
for (i=0;i<255;i++) {
float g = i / 255.0;
glutSetColor(i, g, g, g);
}
}
printf("Loaded %d by %d image\n", ImgWidth, ImgHeight );
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth);
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, 0);
glFogf(GL_FOG_END, 2);
glFogfv(GL_FOG_COLOR, fogColor);
Reset();
}
static void Usage(void)
{
printf("Keys:\n");
printf(" SPACE Reset Parameters\n");
printf(" Up/Down Move image up/down\n");
printf(" Left/Right Move image left/right\n");
printf(" x Decrease X-axis PixelZoom\n");
printf(" X Increase X-axis PixelZoom\n");
printf(" y Decrease Y-axis PixelZoom\n");
printf(" Y Increase Y-axis PixelZoom\n");
printf(" w Decrease glDrawPixels width*\n");
printf(" W Increase glDrawPixels width*\n");
printf(" h Decrease glDrawPixels height*\n");
printf(" H Increase glDrawPixels height*\n");
printf(" p Decrease GL_UNPACK_SKIP_PIXELS*\n");
printf(" P Increase GL_UNPACK_SKIP_PIXELS*\n");
printf(" r Decrease GL_UNPACK_SKIP_ROWS*\n");
printf(" R Increase GL_UNPACK_SKIP_ROWS*\n");
printf(" s Toggle GL_SCISSOR_TEST\n");
printf(" F Toggle GL_FOG\n");
printf(" z Decrease RasterPos Z\n");
printf(" Z Increase RasterPos Z\n");
printf(" f Toggle front/back buffer drawing\n");
printf(" b Benchmark test\n");
printf(" ESC Exit\n");
printf("* Warning: no limits are imposed on these parameters so it's\n");
printf(" possible to cause a segfault if you go too far.\n");
}
int main( int argc, char *argv[] )
{
GLboolean ciMode = GL_FALSE;
const char *filename = IMAGE_FILE;
int i = 1;
if (argc > i && strcmp(argv[i], "-ci")==0) {
ciMode = GL_TRUE;
i++;
}
if (argc > i) {
filename = argv[i];
}
glutInit( &argc, argv );
glutInitWindowPosition( 0, 0 );
glutInitWindowSize( 500, 400 );
if (ciMode)
glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE );
else
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow(argv[0]);
Init(ciMode, filename);
Usage();
glutReshapeFunc( Reshape );
glutKeyboardFunc( Key );
glutSpecialFunc( SpecialKey );
glutDisplayFunc( Display );
glutMainLoop();
return 0;
}

376
progs/demos/drawpix_pbo.c Normal file
View File

@@ -0,0 +1,376 @@
/*
* glDrawPixels demo/test/benchmark
*
* Brian Paul September 25, 1997 This file is in the public domain.
*/
#define GL_GLEXT_PROTOTYPES
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <GL/glut.h>
#include "readtex.h"
#define IMAGE_FILE "../images/tree2.rgba"
static int ImgWidth, ImgHeight;
static GLenum ImgFormat;
static GLenum ImgType = GL_UNSIGNED_BYTE;
static GLubyte *Image = NULL;
static int Xpos, Ypos;
static int SkipPixels, SkipRows;
static int DrawWidth, DrawHeight;
static int Scissor = 0;
static int Fog = 0;
static GLfloat Zpos = -1.0;
static float Xzoom, Yzoom;
static GLboolean DrawFront = GL_FALSE;
static GLboolean Dither = GL_TRUE;
static GLuint DrawPBO;
static void Reset( void )
{
Xpos = Ypos = 20;
DrawWidth = ImgWidth;
DrawHeight = ImgHeight;
SkipPixels = SkipRows = 0;
Scissor = 0;
Fog = 0;
Zpos = -1.0;
Xzoom = Yzoom = 1.0;
}
static void Display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
#if 0
glRasterPos2i(Xpos, Ypos);
#else
/* This allows negative raster positions: */
glRasterPos3f(0, 0, Zpos);
glBitmap(0, 0, 0, 0, Xpos, Ypos, NULL);
#endif
glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels);
glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows);
glPixelZoom( Xzoom, Yzoom );
if (Scissor)
glEnable(GL_SCISSOR_TEST);
if (Fog)
glEnable(GL_FOG);
/*** Draw from the DrawPBO */
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
glDrawPixels(DrawWidth, DrawHeight, ImgFormat, ImgType, NULL);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_FOG);
if (DrawFront)
glFinish();
else
glutSwapBuffers();
}
static void Benchmark( void )
{
int startTime, endTime;
int draws = 500;
double seconds, pixelsPerSecond;
printf("Benchmarking...\n");
/* GL set-up */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels);
glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows);
glPixelZoom( Xzoom, Yzoom );
if (Scissor)
glEnable(GL_SCISSOR_TEST);
if (Fog)
glEnable(GL_FOG);
if (DrawFront)
glDrawBuffer(GL_FRONT);
else
glDrawBuffer(GL_BACK);
/* Run timing test */
draws = 0;
startTime = glutGet(GLUT_ELAPSED_TIME);
do {
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
glDrawPixels(DrawWidth, DrawHeight, ImgFormat, ImgType, NULL);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
draws++;
endTime = glutGet(GLUT_ELAPSED_TIME);
} while (endTime - startTime < 4000); /* 4 seconds */
/* GL clean-up */
glDisable(GL_SCISSOR_TEST);
glDisable(GL_FOG);
/* Results */
seconds = (double) (endTime - startTime) / 1000.0;
pixelsPerSecond = draws * DrawWidth * DrawHeight / seconds;
printf("Result: %d draws in %f seconds = %f pixels/sec\n",
draws, seconds, pixelsPerSecond);
}
static void Reshape( int width, int height )
{
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0, width, 0.0, height, 0.0, 2.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glScissor(width/4, height/4, width/2, height/2);
}
static void Key( unsigned char key, int x, int y )
{
(void) x;
(void) y;
switch (key) {
case ' ':
Reset();
break;
case 'd':
Dither = !Dither;
if (Dither)
glEnable(GL_DITHER);
else
glDisable(GL_DITHER);
break;
case 'w':
if (DrawWidth > 0)
DrawWidth--;
break;
case 'W':
DrawWidth++;
break;
case 'h':
if (DrawHeight > 0)
DrawHeight--;
break;
case 'H':
DrawHeight++;
break;
case 'p':
if (SkipPixels > 0)
SkipPixels--;
break;
case 'P':
SkipPixels++;
break;
case 'r':
if (SkipRows > 0)
SkipRows--;
break;
case 'R':
SkipRows++;
break;
case 's':
Scissor = !Scissor;
break;
case 'x':
Xzoom -= 0.1;
break;
case 'X':
Xzoom += 0.1;
break;
case 'y':
Yzoom -= 0.1;
break;
case 'Y':
Yzoom += 0.1;
break;
case 'z':
Zpos -= 0.1;
printf("RasterPos Z = %g\n", Zpos);
break;
case 'Z':
Zpos += 0.1;
printf("RasterPos Z = %g\n", Zpos);
break;
case 'b':
Benchmark();
break;
case 'F':
Fog = !Fog;
printf("Fog %d\n", Fog);
break;
case 'f':
DrawFront = !DrawFront;
if (DrawFront)
glDrawBuffer(GL_FRONT);
else
glDrawBuffer(GL_BACK);
printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK");
break;
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void SpecialKey( int key, int x, int y )
{
(void) x;
(void) y;
switch (key) {
case GLUT_KEY_UP:
Ypos += 1;
break;
case GLUT_KEY_DOWN:
Ypos -= 1;
break;
case GLUT_KEY_LEFT:
Xpos -= 1;
break;
case GLUT_KEY_RIGHT:
Xpos += 1;
break;
}
glutPostRedisplay();
}
static void Init( GLboolean ciMode, const char *filename )
{
static const GLfloat fogColor[4] = {0, 1, 0, 0};
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
Image = LoadRGBImage( filename, &ImgWidth, &ImgHeight, &ImgFormat );
if (!Image) {
printf("Couldn't read %s\n", filename);
exit(0);
}
if (ciMode) {
/* Convert RGB image to grayscale */
GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight );
GLint i;
for (i=0; i<ImgWidth*ImgHeight; i++) {
int gray = Image[i*3] + Image[i*3+1] + Image[i*3+2];
indexImage[i] = gray / 3;
}
free(Image);
Image = indexImage;
ImgFormat = GL_COLOR_INDEX;
for (i=0;i<255;i++) {
float g = i / 255.0;
glutSetColor(i, g, g, g);
}
}
printf("Loaded %d by %d image\n", ImgWidth, ImgHeight );
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth);
/* put image into DrawPBO */
glGenBuffersARB(1, &DrawPBO);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, DrawPBO);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
ImgWidth * ImgHeight * 4, Image, GL_STATIC_DRAW);
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, 0);
glFogf(GL_FOG_END, 2);
glFogfv(GL_FOG_COLOR, fogColor);
Reset();
}
static void Usage(void)
{
printf("Keys:\n");
printf(" SPACE Reset Parameters\n");
printf(" Up/Down Move image up/down\n");
printf(" Left/Right Move image left/right\n");
printf(" x Decrease X-axis PixelZoom\n");
printf(" X Increase X-axis PixelZoom\n");
printf(" y Decrease Y-axis PixelZoom\n");
printf(" Y Increase Y-axis PixelZoom\n");
printf(" w Decrease glDrawPixels width*\n");
printf(" W Increase glDrawPixels width*\n");
printf(" h Decrease glDrawPixels height*\n");
printf(" H Increase glDrawPixels height*\n");
printf(" p Decrease GL_UNPACK_SKIP_PIXELS*\n");
printf(" P Increase GL_UNPACK_SKIP_PIXELS*\n");
printf(" r Decrease GL_UNPACK_SKIP_ROWS*\n");
printf(" R Increase GL_UNPACK_SKIP_ROWS*\n");
printf(" s Toggle GL_SCISSOR_TEST\n");
printf(" F Toggle GL_FOG\n");
printf(" z Decrease RasterPos Z\n");
printf(" Z Increase RasterPos Z\n");
printf(" f Toggle front/back buffer drawing\n");
printf(" b Benchmark test\n");
printf(" ESC Exit\n");
printf("* Warning: no limits are imposed on these parameters so it's\n");
printf(" possible to cause a segfault if you go too far.\n");
}
int main( int argc, char *argv[] )
{
GLboolean ciMode = GL_FALSE;
const char *filename = IMAGE_FILE;
int i = 1;
if (argc > i && strcmp(argv[i], "-ci")==0) {
ciMode = GL_TRUE;
i++;
}
if (argc > i) {
filename = argv[i];
}
glutInit( &argc, argv );
glutInitWindowPosition( 0, 0 );
glutInitWindowSize( 500, 400 );
if (ciMode)
glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE );
else
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow(argv[0]);
Init(ciMode, filename);
Usage();
glutReshapeFunc( Reshape );
glutKeyboardFunc( Key );
glutSpecialFunc( SpecialKey );
glutDisplayFunc( Display );
glutMainLoop();
return 0;
}

486
progs/demos/gearbox.c Normal file
View File

@@ -0,0 +1,486 @@
/*
* Use glCopyTexSubImage2D to draw animated gears on the sides of a box.
*
* Brian Paul
* 27 January 2006
*/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glut.h>
#ifndef M_PI
#define M_PI 3.14159265
#endif
static GLint WinWidth = 800, WinHeight = 500;
static GLint TexWidth, TexHeight;
static GLuint TexObj = 1;
static GLenum IntFormat = GL_RGBA;
static GLboolean WireFrame = GL_FALSE;
static GLint T0 = 0;
static GLint Frames = 0;
static GLint Win = 0;
static GLfloat ViewRotX = 20.0, ViewRotY = 30.0, ViewRotZ = 0.0;
static GLint Gear1, Gear2, Gear3;
static GLfloat GearRot = 0.0;
static GLfloat CubeRot = 0.0;
/**
Draw a gear wheel. You'll probably want to call this function when
building a display list since we do a lot of trig here.
Input: inner_radius - radius of hole at center
outer_radius - radius at center of teeth
width - width of gear
teeth - number of teeth
tooth_depth - depth of tooth
**/
static void
gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
GLint teeth, GLfloat tooth_depth)
{
GLint i;
GLfloat r0, r1, r2;
GLfloat angle, da;
GLfloat u, v, len;
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
da = 2.0 * M_PI / teeth / 4.0;
glShadeModel(GL_FLAT);
glNormal3f(0.0, 0.0, 1.0);
/* draw front face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
if (i < teeth) {
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
}
}
glEnd();
/* draw front sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
}
glEnd();
glNormal3f(0.0, 0.0, -1.0);
/* draw back face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
if (i < teeth) {
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
}
}
glEnd();
/* draw back sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
}
glEnd();
/* draw outward faces of teeth */
glBegin(GL_QUAD_STRIP);
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
u = r2 * cos(angle + da) - r1 * cos(angle);
v = r2 * sin(angle + da) - r1 * sin(angle);
len = sqrt(u * u + v * v);
u /= len;
v /= len;
glNormal3f(v, -u, 0.0);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
glNormal3f(v, -u, 0.0);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
}
glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
glEnd();
glShadeModel(GL_SMOOTH);
/* draw inside radius cylinder */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glNormal3f(-cos(angle), -sin(angle), 0.0);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
}
glEnd();
}
static void
cleanup(void)
{
glDeleteTextures(1, &TexObj);
glDeleteLists(Gear1, 1);
glDeleteLists(Gear2, 1);
glDeleteLists(Gear3, 1);
glutDestroyWindow(Win);
}
static void
DrawGears(void)
{
if (WireFrame) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
glPushMatrix();
glRotatef(20/*ViewRotX*/, 1.0, 0.0, 0.0);
glRotatef(ViewRotY, 0.0, 1.0, 0.0);
glRotatef(ViewRotZ, 0.0, 0.0, 1.0);
glPushMatrix();
glTranslatef(-3.0, -2.0, 0.0);
glRotatef(GearRot, 0.0, 0.0, 1.0);
glCallList(Gear1);
glPopMatrix();
glPushMatrix();
glTranslatef(3.1, -2.0, 0.0);
glRotatef(-2.0 * GearRot - 9.0, 0.0, 0.0, 1.0);
glCallList(Gear2);
glPopMatrix();
glPushMatrix();
glTranslatef(-3.1, 4.2, 0.0);
glRotatef(-2.0 * GearRot - 25.0, 0.0, 0.0, 1.0);
glCallList(Gear3);
glPopMatrix();
glPopMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
static void
DrawCube(void)
{
static const GLfloat texcoords[4][2] = {
{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
};
static const GLfloat vertices[4][2] = {
{ -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
};
static const GLfloat xforms[6][4] = {
{ 0, 0, 1, 0 },
{ 90, 0, 1, 0 },
{ 180, 0, 1, 0 },
{ 270, 0, 1, 0 },
{ 90, 1, 0, 0 },
{ -90, 1, 0, 0 }
};
static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 };
GLint i, j;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glRotatef(ViewRotX, 1.0, 0.0, 0.0);
glRotatef(15, 1, 0, 0);
glRotatef(CubeRot, 0, 1, 0);
glScalef(4, 4, 4);
for (i = 0; i < 6; i++) {
glPushMatrix();
glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
glTranslatef(0, 0, 1.1);
glBegin(GL_POLYGON);
glNormal3f(0, 0, 1);
for (j = 0; j < 4; j++) {
glTexCoord2fv(texcoords[j]);
glVertex2fv(vertices[j]);
}
glEnd();
glPopMatrix();
}
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
static void
draw(void)
{
float ar;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -40.0);
glDisable(GL_SCISSOR_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
/* draw gears */
glViewport(0, 0, TexWidth, TexHeight);
glScissor(0, 0, TexWidth, TexHeight);
glClearColor(0.5, 0.5, 0.8, 0.0);
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 60.0);
glMatrixMode(GL_MODELVIEW);
DrawGears();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
/* draw textured cube */
glViewport(TexWidth, 0, WinWidth - TexWidth, WinHeight);
glScissor(TexWidth, 0, WinWidth - TexWidth, WinHeight);
glClearColor(0.5, 0.5, 0.8, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
ar = (float) (WinWidth - TexWidth) / WinHeight;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
glMatrixMode(GL_MODELVIEW);
DrawCube();
/* finish up */
glutSwapBuffers();
Frames++;
{
GLint t = glutGet(GLUT_ELAPSED_TIME);
if (t - T0 >= 5000) {
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
T0 = t;
Frames = 0;
}
}
}
static void
idle(void)
{
static double t0 = -1.;
double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
if (t0 < 0.0)
t0 = t;
dt = t - t0;
t0 = t;
GearRot += 70.0 * dt; /* 70 degrees per second */
GearRot = fmod(GearRot, 360.0); /* prevents eventual overflow */
CubeRot += 15.0 * dt;
glutPostRedisplay();
}
/* change view angle, exit upon ESC */
static void
key(unsigned char k, int x, int y)
{
(void) x;
(void) y;
switch (k) {
case 'w':
WireFrame = !WireFrame;
break;
case 'z':
ViewRotZ += 5.0;
break;
case 'Z':
ViewRotZ -= 5.0;
break;
case 27: /* Escape */
cleanup();
exit(0);
break;
default:
return;
}
glutPostRedisplay();
}
/* change view angle */
static void
special(int k, int x, int y)
{
(void) x;
(void) y;
switch (k) {
case GLUT_KEY_UP:
ViewRotX += 5.0;
break;
case GLUT_KEY_DOWN:
ViewRotX -= 5.0;
break;
case GLUT_KEY_LEFT:
ViewRotY += 5.0;
break;
case GLUT_KEY_RIGHT:
ViewRotY -= 5.0;
break;
default:
return;
}
glutPostRedisplay();
}
/* new window size or exposure */
static void
reshape(int width, int height)
{
WinWidth = width;
WinHeight = height;
}
static void
init(int argc, char *argv[])
{
static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
GLint i;
glLightfv(GL_LIGHT0, GL_POSITION, pos);
#if 0
glEnable(GL_CULL_FACE);
#endif
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
/* make the gears */
Gear1 = glGenLists(1);
glNewList(Gear1, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
gear(1.0, 4.0, 1.0, 20, 0.7);
glEndList();
Gear2 = glGenLists(1);
glNewList(Gear2, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
gear(0.5, 2.0, 2.0, 10, 0.7);
glEndList();
Gear3 = glGenLists(1);
glNewList(Gear3, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
gear(1.3, 2.0, 0.5, 10, 0.7);
glEndList();
glEnable(GL_NORMALIZE);
/* xxx make size dynamic */
TexWidth = 256;
TexHeight = 256;
glBindTexture(GL_TEXTURE_2D, TexObj);
glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
for ( i=1; i<argc; i++ ) {
if (strcmp(argv[i], "-info")==0) {
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
}
}
}
static void
visible(int vis)
{
if (vis == GLUT_VISIBLE)
glutIdleFunc(idle);
else
glutIdleFunc(NULL);
}
int
main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(WinWidth, WinHeight);
Win = glutCreateWindow("gearbox");
init(argc, argv);
glutDisplayFunc(draw);
glutReshapeFunc(reshape);
glutKeyboardFunc(key);
glutSpecialFunc(special);
glutVisibilityFunc(visible);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}

View File

@@ -38,8 +38,8 @@
#include <GL/glut.h>
static GLsizei MaxSize = 1024;
static GLsizei TexWidth = 256, TexHeight = 256, TexBorder = 0;
static GLsizei MaxSize = 2048;
static GLsizei TexWidth = 1024, TexHeight = 1024, TexBorder = 0;
static GLboolean ScaleAndBias = GL_FALSE;
static GLboolean SubImage = GL_FALSE;
static GLdouble DownloadRate = 0.0; /* texels/sec */
@@ -47,6 +47,32 @@ static GLdouble DownloadRate = 0.0; /* texels/sec */
static GLuint Mode = 0;
/* Try and avoid L2 cache effects by cycling through a small number of
* textures.
*
* At the initial size of 1024x1024x4 == 4mbyte, say 8 textures will
* keep us out of most caches at 32mb total.
*
* This turns into a fairly interesting question of what exactly you
* expect to be in cache in normal usage, and what you think should be
* outside. There's no rules for this, no reason to favour one usage
* over another except what the application you care about happens to
* resemble most closely.
*
* - Should the client texture image be in L2 cache? Has it just been
* generated or read from disk?
* - Does the application really use >1 texture, or is it constantly
* updating one image in-place?
*
* Different answers will favour different texture upload mechanisms.
* To upload an image that is purely outside of cache, a DMA-based
* upload will probably win, whereas for small, in-cache textures,
* copying looks good.
*/
#define NR_TEXOBJ 4
static GLuint TexObj[NR_TEXOBJ];
struct FormatRec {
GLenum Format;
GLenum Type;
@@ -116,25 +142,57 @@ TypeStr(GLenum type)
}
}
/* On x86, there is a performance cliff for memcpy to texture memory
* for sources below 64 byte alignment. We do our best with this in
* the driver, but it is better if the images are correctly aligned to
* start with:
*/
#define ALIGN (1<<12)
static unsigned align(unsigned value, unsigned a)
{
return (value + a - 1) & ~(a-1);
}
static int MIN2(int a, int b)
{
return a < b ? a : b;
}
static void
MeasureDownloadRate(void)
{
const int w = TexWidth + 2 * TexBorder;
const int h = TexHeight + 2 * TexBorder;
const int bytes = w * h * BytesPerTexel(Format);
const int image_bytes = align(w * h * BytesPerTexel(Format), ALIGN);
const int bytes = image_bytes * NR_TEXOBJ;
GLubyte *orig_texImage, *orig_getImage;
GLubyte *texImage, *getImage;
GLdouble t0, t1, time;
int count;
int i;
int offset = 0;
GLdouble total = 0; /* ints will tend to overflow */
texImage = (GLubyte *) malloc(bytes);
getImage = (GLubyte *) malloc(bytes);
if (!texImage || !getImage) {
printf("allocating %d bytes for %d %dx%d images\n",
bytes, NR_TEXOBJ, w, h);
orig_texImage = (GLubyte *) malloc(bytes + ALIGN);
orig_getImage = (GLubyte *) malloc(image_bytes + ALIGN);
if (!orig_texImage || !orig_getImage) {
DownloadRate = 0.0;
return;
}
printf("alloc %p %p\n", orig_texImage, orig_getImage);
texImage = (GLubyte *)align((unsigned)orig_texImage, ALIGN);
getImage = (GLubyte *)align((unsigned)orig_getImage, ALIGN);
for (i = 1; !(((unsigned)texImage) & i); i<<=1)
;
printf("texture image alignment: %d bytes (%p)\n", i, texImage);
for (i = 0; i < bytes; i++) {
texImage[i] = i & 0xff;
}
@@ -166,51 +224,80 @@ MeasureDownloadRate(void)
count = 0;
t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
do {
int img = count%NR_TEXOBJ;
GLubyte *img_ptr = texImage + img * image_bytes;
glBindTexture(GL_TEXTURE_2D, TexObj[img]);
if (SubImage && count > 0) {
glTexSubImage2D(GL_TEXTURE_2D, 0, -TexBorder, -TexBorder, w, h,
/* Only update a portion of the image each iteration. This
* is presumably why you'd want to use texsubimage, otherwise
* you may as well just call teximage again.
*
* A bigger question is whether to use a pointer that moves
* with each call, ie does the incoming data come from L2
* cache under normal circumstances, or is it pulled from
* uncached memory?
*
* There's a good argument to say L2 cache, ie you'd expect
* the data to have been recently generated. It's possible
* that it could have come from a file read, which may or may
* not have gone through the cpu.
*/
glTexSubImage2D(GL_TEXTURE_2D, 0,
-TexBorder,
-TexBorder + offset * h/8,
w,
h/8,
FormatTable[Format].Format,
FormatTable[Format].Type, texImage);
FormatTable[Format].Type,
#if 1
texImage /* likely in L2$ */
#else
img_ptr + offset * bytes/8 /* unlikely in L2$ */
#endif
);
offset += 1;
offset %= 8;
total += w * h / 8;
}
else {
glTexImage2D(GL_TEXTURE_2D, 0,
FormatTable[Format].IntFormat, w, h, TexBorder,
FormatTable[Format].Format,
FormatTable[Format].Type, texImage);
FormatTable[Format].Type,
img_ptr);
total += w*h;
}
#if 1
/* Render a texture, but not necessarily the one just uploaded.
*/
/* glBindTexture(GL_TEXTURE_2D, TexObj[(img + NR_TEXOBJ/2)%NR_TEXOBJ]); */
/* draw a tiny polygon to force texture into texram */
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0); glVertex2f(1, 1);
glTexCoord2f(1, 0); glVertex2f(3, 1);
glTexCoord2f(0.5, 1); glVertex2f(2, 3);
glEnd();
/* glFinish(); */
#endif
t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
time = t1 - t0;
count++;
/* printf("total %f count %d\n", total, count); */
} while (time < 3.0);
glDisable(GL_TEXTURE_2D);
printf("w*h=%d count=%d time=%f\n", w*h, count, time);
DownloadRate = w * h * count / time;
printf("total texels=%f time=%f\n", total, time);
DownloadRate = total / time;
#if 0
if (!ScaleAndBias) {
/* verify texture readback */
glGetTexImage(GL_TEXTURE_2D, 0,
FormatTable[Format].Format,
FormatTable[Format].Type, getImage);
for (i = 0; i < w * h; i++) {
if (texImage[i] != getImage[i]) {
printf("[%d] %d != %d\n", i, texImage[i], getImage[i]);
}
}
}
#endif
free(texImage);
free(getImage);
free(orig_texImage);
free(orig_getImage);
{
GLint err = glGetError();

View File

@@ -29,6 +29,7 @@ SOURCES = antialias.c \
dinoshade.c \
floattex.c \
fbotest1.c \
fbotest2.c \
fbotexture.c \
fog.c \
fogcoord.c \
@@ -47,6 +48,7 @@ SOURCES = antialias.c \
sharedtex.c \
stencilwrap.c \
stencil_wrap.c \
subtexrate.c \
tex1d.c \
texfilt.c \
texline.c \

204
progs/tests/fbotest2.c Normal file
View File

@@ -0,0 +1,204 @@
/*
* Test GL_EXT_framebuffer_object
*
* Brian Paul
* 19 Mar 2006
*/
#define GL_GLEXT_PROTOTYPES
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
static int Width = 400, Height = 400;
static GLuint MyFB, ColorRb, DepthRb;
static GLboolean Animate = GL_FALSE;
static GLfloat Rotation = 0.0;
static void
CheckError(int line)
{
GLenum err = glGetError();
if (err) {
printf("fbotest1: GL Error 0x%x at line %d\n", (int) err, line);
}
}
static void
Display( void )
{
GLubyte *buffer = malloc(Width * Height * 4);
GLenum status;
printf("Drawing\n");
CheckError(__LINE__);
/* draw to user framebuffer */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
printf("fbotest1: Error: Framebuffer is incomplete!!!\n");
}
CheckError(__LINE__);
glClearColor(0.5, 0.5, 1.0, 0.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glPushMatrix();
glRotatef(30.0, 1, 0, 0);
glRotatef(Rotation, 0, 1, 0);
glutSolidTeapot(2.0);
glPopMatrix();
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
/* read from user framebuffer */
glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
/* draw to window */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glWindowPos2iARB(0, 0);
glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
free(buffer);
glutSwapBuffers();
CheckError(__LINE__);
}
static void
Reshape( int width, int height )
{
float ar = (float) width / (float) height;
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum( -ar, ar, -1.0, 1.0, 5.0, 25.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -15.0 );
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
width, height);
Width = width;
Height = height;
}
static void
CleanUp(void)
{
glDeleteFramebuffersEXT(1, &MyFB);
glDeleteRenderbuffersEXT(1, &ColorRb);
glDeleteRenderbuffersEXT(1, &DepthRb);
assert(!glIsFramebufferEXT(MyFB));
assert(!glIsRenderbufferEXT(ColorRb));
assert(!glIsRenderbufferEXT(DepthRb));
exit(0);
}
static void
Idle(void)
{
Rotation = glutGet(GLUT_ELAPSED_TIME) * 0.1;
glutPostRedisplay();
}
static void
Key( unsigned char key, int x, int y )
{
(void) x;
(void) y;
switch (key) {
case 'a':
Animate = !Animate;
if (Animate)
glutIdleFunc(Idle);
else
glutIdleFunc(NULL);
break;
case 27:
CleanUp();
break;
}
glutPostRedisplay();
}
static void
Init( void )
{
if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
printf("fbotest1: GL_EXT_framebuffer_object not found!\n");
exit(0);
}
printf("fbotest1: GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
glGenFramebuffersEXT(1, &MyFB);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
assert(glIsFramebufferEXT(MyFB));
/* set color buffer */
glGenRenderbuffersEXT(1, &ColorRb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb);
assert(glIsRenderbufferEXT(ColorRb));
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
GL_RENDERBUFFER_EXT, ColorRb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
/* setup depth buffer */
glGenRenderbuffersEXT(1, &DepthRb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRb);
assert(glIsRenderbufferEXT(DepthRb));
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, DepthRb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, Width, Height);
CheckError(__LINE__);
/* restore to default */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
CheckError(__LINE__);
}
int
main( int argc, char *argv[] )
{
glutInit( &argc, argv );
glutInitWindowPosition( 0, 0 );
glutInitWindowSize(Width, Height);
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
glutCreateWindow(argv[0]);
glutReshapeFunc( Reshape );
glutKeyboardFunc( Key );
glutDisplayFunc( Display );
if (Animate)
glutIdleFunc(Idle);
Init();
glutMainLoop();
return 0;
}

View File

@@ -17,6 +17,10 @@
#include <string.h>
#include <math.h>
/* For debug */
#define DEPTH 1
#define STENCIL 1
static int Width = 400, Height = 400;
static int TexWidth = 512, TexHeight = 512;
@@ -76,10 +80,14 @@ RenderTexture(void)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
CheckError(__LINE__);
#if DEPTH
glEnable(GL_DEPTH_TEST);
#if STENCIL
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NEVER, 1, ~0);
glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
#endif
CheckError(__LINE__);
@@ -93,10 +101,13 @@ RenderTexture(void)
glEnd();
/* draw teapot where stencil != 1 */
#if STENCIL
glStencilFunc(GL_NOTEQUAL, 1, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
#endif
CheckError(__LINE__);
#endif
#if 0
glBegin(GL_POLYGON);
@@ -184,9 +195,13 @@ Reshape(int width, int height)
static void
CleanUp(void)
{
#if DEPTH
glDeleteRenderbuffersEXT(1, &DepthRB);
#endif
#if STENCIL
if (!UsePackedDepthStencil)
glDeleteRenderbuffersEXT(1, &StencilRB);
#endif
glDeleteFramebuffersEXT(1, &MyFB);
glDeleteTextures(1, &TexObj);
@@ -253,6 +268,7 @@ Init(int argc, char *argv[])
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
assert(i == MyFB);
#if DEPTH
/* make depth renderbuffer */
glGenRenderbuffersEXT(1, &DepthRB);
assert(DepthRB);
@@ -275,9 +291,11 @@ Init(int argc, char *argv[])
/* attach DepthRB to MyFB */
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, DepthRB);
#endif
CheckError(__LINE__);
#if STENCIL
if (UsePackedDepthStencil) {
/* DepthRb is a combined depth/stencil renderbuffer */
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
@@ -303,7 +321,7 @@ Init(int argc, char *argv[])
CheckError(__LINE__);
printf("Stencil renderbuffer size = %d bits\n", i);
assert(i > 0);
#endif
/* bind regular framebuffer */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

View File

@@ -15,7 +15,7 @@
#include "../util/readtex.c" /* a hack, I know */
#define IMAGE_FILE "../images/girl.rgb"
#define IMAGE_FILE "../images/tree2.rgba"
static int ImgWidth, ImgHeight;
static GLenum ImgFormat;
@@ -32,8 +32,8 @@ static GLboolean Benchmark = GL_FALSE;
static GLuint DrawPBO, TempPBO;
static GLenum ReadFormat = GL_RGBA;
static GLenum ReadType = GL_UNSIGNED_BYTE;
static GLenum ReadFormat = GL_BGRA;
static GLenum ReadType = GL_UNSIGNED_INT_8_8_8_8_REV;

378
progs/tests/subtexrate.c Normal file
View File

@@ -0,0 +1,378 @@
/*
* Measure glTexSubImage and glCopyTexSubImage speed
*
* Brian Paul
* 26 Jan 2006
*/
#define GL_GLEXT_PROTOTYPES
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
static GLint WinWidth = 1024, WinHeight = 512;
static GLint TexWidth = 512, TexHeight = 512;
static GLuint TexObj = 1;
static GLenum IntFormat = GL_RGBA;
static GLenum ReadFormat = GL_BGRA; /* for glReadPixels */
static GLboolean DrawQuad = GL_TRUE;
/**
* draw teapot image, size TexWidth by TexHeight
*/
static void
DrawTestImage(void)
{
GLfloat ar;
glViewport(0, 0, TexWidth, TexHeight);
glScissor(0, 0, TexWidth, TexHeight);
glEnable(GL_SCISSOR_TEST);
glClearColor(0.5, 0.5, 0.5, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ar = (float) TexWidth / TexHeight;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CW);
glPushMatrix();
glRotatef(45, 1, 0, 0);
glRotatef(45, 0, 1, 0);
glutSolidTeapot(2.3);
glPopMatrix();
glFrontFace(GL_CCW);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, WinWidth, WinHeight);
glFinish();
}
/**
* Do glCopyTexSubImage2D call (update texture with framebuffer data)
* If doSubRect is true, do the copy in four pieces instead of all at once.
*/
static void
DoCopyTex(GLboolean doSubRect)
{
if (doSubRect) {
/* copy in four parts */
int w = TexWidth / 2, h = TexHeight / 2;
int x0 = 0, y0 = 0;
int x1 = w, y1 = h;
#if 0
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x0, y0, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x1, y0, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x0, y1, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x1, y1, w, h);
#else
/* scramble */
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x1, y1, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x0, y1, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x1, y0, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x0, y0, w, h);
#endif
}
else {
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
}
}
/**
* Do glTexSubImage2D (update texture w/ user data)
* If doSubRect, do update in four pieces, else all at once.
*/
static void
SubTex(GLboolean doSubRect, const GLubyte *image)
{
if (doSubRect) {
/* four pieces */
int w = TexWidth / 2, h = TexHeight / 2;
int x0 = 0, y0 = 0;
int x1 = w, y1 = h;
glPixelStorei(GL_UNPACK_ROW_LENGTH, TexWidth);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei( GL_PACK_INVERT_MESA, GL_TRUE );
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, w, h,
ReadFormat, GL_UNSIGNED_BYTE, image);
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */
glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, w, h,
ReadFormat, GL_UNSIGNED_BYTE, image);
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, w, h,
ReadFormat, GL_UNSIGNED_BYTE, image);
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */
glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, w, h,
ReadFormat, GL_UNSIGNED_BYTE, image);
glPixelStorei( GL_PACK_INVERT_MESA, GL_FALSE );
}
else {
/* all at once */
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexWidth, TexHeight,
ReadFormat, GL_UNSIGNED_BYTE, image);
}
}
/**
* Measure gl[Copy]TexSubImage rate.
* This actually also includes time to render a quad and SwapBuffers.
*/
static void
RunTest(GLboolean copyTex, GLboolean doSubRect)
{
double t0, t1;
int iters = 0;
float copyRate, mbRate;
float rot = 0.0;
int bpp, r, g, b, a;
int w, h;
GLubyte *image = NULL;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a);
bpp = (r + g + b + a) / 8;
if (!copyTex) {
/* read image from frame buffer */
image = (GLubyte *) malloc(TexWidth * TexHeight * bpp);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, TexWidth, TexHeight,
ReadFormat, GL_UNSIGNED_BYTE, image);
}
glEnable(GL_TEXTURE_2D);
glViewport(WinWidth / 2, 0, WinWidth / 2, WinHeight);
t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
if (!DrawQuad)
glDrawBuffer(GL_FRONT);
do {
if (copyTex)
/* Framebuffer -> Texture */
DoCopyTex(doSubRect);
else {
/* Main Mem -> Texture */
SubTex(doSubRect, image);
}
/* draw textured quad */
if (DrawQuad) {
glPushMatrix();
glRotatef(rot, 0, 0, 1);
glTranslatef(1, 0, 0);
glBegin(GL_POLYGON);
glTexCoord2f(0, 0); glVertex2f(-1, -1);
glTexCoord2f(1, 0); glVertex2f( 1, -1);
glTexCoord2f(1, 1); glVertex2f( 1, 1);
glTexCoord2f(0, 1); glVertex2f(-1, 1);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
else {
/* Draw something tiny to ensure that the texture is really
* uploaded:
*/
glPushMatrix();
glRotatef(rot, 0, 0, 1);
glTranslatef(1, 0, 0);
glBegin(GL_POLYGON);
glTexCoord2f(0, 0); glVertex2f(-.01, -.01);
glTexCoord2f(.01, 0); glVertex2f( .01, -.01);
glTexCoord2f(.01, .01); glVertex2f( .01, .01);
glTexCoord2f(0, .01); glVertex2f(-.01, .01);
glEnd();
glPopMatrix();
glFlush();
}
iters++;
rot += 2.0;
t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
} while (t1 - t0 < 2.0);
/* Make sure everything is done before taking the final timing:
*/
glFinish();
t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
glDisable(GL_TEXTURE_2D);
if (image)
free(image);
if (doSubRect) {
w = TexWidth / 2;
h = TexHeight / 2;
iters *= 4;
}
else {
w = TexWidth;
h = TexHeight;
}
copyRate = iters / (t1 - t0);
mbRate = w * h * bpp * copyRate / (1024 * 1024);
if (copyTex)
printf("glCopyTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp);
else
printf("glTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp);
printf(" %d calls in %.2f = %.2f calls/sec, %.2f MB/s\n",
iters, t1-t0, copyRate, mbRate);
}
static void
Draw(void)
{
glClearColor(0.2, 0.2, 0.8, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawTestImage();
if (!DrawQuad) {
glutSwapBuffers();
}
RunTest(GL_FALSE, GL_FALSE);
RunTest(GL_FALSE, GL_TRUE);
RunTest(GL_TRUE, GL_FALSE);
RunTest(GL_TRUE, GL_TRUE);
glutSwapBuffers();
/* printf("exiting\n"); */
/* exit(0); */
}
static void
Reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -15.0);
}
static void
Key(unsigned char key, int x, int y)
{
(void) x;
(void) y;
switch (key) {
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void
SpecialKey(int key, int x, int y)
{
(void) x;
(void) y;
switch (key) {
case GLUT_KEY_UP:
break;
case GLUT_KEY_DOWN:
break;
case GLUT_KEY_LEFT:
break;
case GLUT_KEY_RIGHT:
break;
}
glutPostRedisplay();
}
static void
Init(void)
{
/* create initial, empty teximage */
glBindTexture(GL_TEXTURE_2D, TexObj);
glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
static void
ParseArgs(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-nodraw") == 0)
DrawQuad = GL_FALSE;
}
}
int
main(int argc, char *argv[])
{
GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH;
glutInit(&argc, argv);
ParseArgs(argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize(WinWidth, WinHeight);
glutInitDisplayMode(mode);
glutCreateWindow(argv[0]);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutSpecialFunc(SpecialKey);
glutDisplayFunc(Draw);
printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
Init();
glutMainLoop();
return 0;
}

View File

@@ -687,4 +687,15 @@ extern int __glXGetInternalVersion(void);
/* Get the unadjusted system time */
extern int __glXGetUST( int64_t * ust );
/* KW: Temporary hacks to coalesce multiple opens of the same drm
* instance. These should be renamed or moved to libdrm, or the
* behaviour of drmOpen/drmClose should change.
*/
int drmOpenOnce(void *unused,
const char *BusID,
int *newlyopened);
void drmCloseOnce(int fd);
#endif /* !__GLX_client_h__ */

View File

@@ -702,6 +702,68 @@ static const __DRIinterfaceMethods interface_methods = {
glXGetMscRateOML,
};
#define DRM_MAX_FDS 16
static struct {
char *BusID;
int fd;
int refcount;
} connection[DRM_MAX_FDS];
static int nr_fds = 0;
int drmOpenOnce(void *unused,
const char *BusID,
int *newlyopened)
{
int i;
int fd;
for (i = 0; i < nr_fds; i++)
if (strcmp(BusID, connection[i].BusID) == 0) {
connection[i].refcount++;
*newlyopened = 0;
return connection[i].fd;
}
fd = drmOpen(unused, BusID);
if (fd <= 0 || nr_fds == DRM_MAX_FDS)
return fd;
connection[nr_fds].BusID = strdup(BusID);
connection[nr_fds].fd = fd;
connection[nr_fds].refcount = 1;
*newlyopened = 1;
fprintf(stderr, "saved connection %d for %s %d\n",
nr_fds, connection[nr_fds].BusID,
strcmp(BusID, connection[nr_fds].BusID));
nr_fds++;
return fd;
}
void drmCloseOnce(int fd)
{
int i;
for (i = 0; i < nr_fds; i++) {
if (fd == connection[i].fd) {
if (--connection[i].refcount == 0) {
drmClose(connection[i].fd);
free(connection[i].BusID);
if (i < --nr_fds)
connection[i] = connection[nr_fds];
return;
}
}
}
}
/**
* Perform the required libGL-side initialization and call the client-side
@@ -753,7 +815,8 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
framebuffer.dev_priv = NULL;
if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
fd = drmOpen(NULL,BusID);
int newlyopened;
fd = drmOpenOnce(NULL,BusID, &newlyopened);
Xfree(BusID); /* No longer needed */
err_msg = "open DRM";
@@ -780,7 +843,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
}
err_msg = "XF86DRIAuthConnection";
if (XF86DRIAuthConnection(dpy, scrn, magic)) {
if (!newlyopened || XF86DRIAuthConnection(dpy, scrn, magic)) {
char *driverName;
/*
@@ -884,7 +947,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
}
if ( fd >= 0 ) {
(void)drmClose(fd);
(void)drmCloseOnce(fd);
}
(void)XF86DRICloseConnection(dpy, scrn);

View File

@@ -206,10 +206,15 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
#if FEATURE_EXT_framebuffer_object
driver->NewFramebuffer = _mesa_new_framebuffer;
driver->NewRenderbuffer = _mesa_new_soft_renderbuffer;
driver->RenderbufferTexture = _mesa_renderbuffer_texture;
driver->RenderTexture = _mesa_render_texture;
driver->FinishRenderTexture = _mesa_finish_render_texture;
driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
#endif
#if FEATURE_EXT_framebuffer_blit
driver->BlitFramebuffer = _swrast_BlitFramebuffer;
#endif
/* query objects */
driver->NewQueryObject = _mesa_new_query_object;
driver->BeginQuery = NULL;

View File

@@ -89,7 +89,7 @@ $(LIB_DIR)/$(LIBNAME): $(LIBNAME)
depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \
> /dev/null
>& /dev/null
# Emacs tags

View File

@@ -829,7 +829,7 @@ static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPriv
(void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
_mesa_free(psp->pDevPriv);
(void)drmClose(psp->fd);
(void)drmCloseOnce(psp->fd);
if ( psp->modes != NULL ) {
(*dri_interface->destroyContextModes)( psp->modes );
}

View File

@@ -56,6 +56,8 @@ driNewRenderbuffer(GLenum format, GLvoid *addr,
driRenderbuffer *drb;
assert(format == GL_RGBA ||
format == GL_RGB5 ||
format == GL_RGBA8 ||
format == GL_DEPTH_COMPONENT16 ||
format == GL_DEPTH_COMPONENT24 ||
format == GL_DEPTH_COMPONENT32 ||
@@ -75,7 +77,7 @@ driNewRenderbuffer(GLenum format, GLvoid *addr,
drb->Base.InternalFormat = format;
if (format == GL_RGBA) {
if (format == GL_RGBA || format == GL_RGB5 || format == GL_RGBA8) {
/* Color */
drb->Base._BaseFormat = GL_RGBA;
drb->Base.DataType = GL_UNSIGNED_BYTE;
@@ -94,7 +96,7 @@ driNewRenderbuffer(GLenum format, GLvoid *addr,
}
else {
/* Stencil */
ASSERT(format == GL_STENCIL_INDEX8);
ASSERT(format == GL_STENCIL_INDEX8_EXT);
drb->Base._BaseFormat = GL_STENCIL_INDEX;
drb->Base.DataType = GL_UNSIGNED_BYTE;
}

View File

@@ -5,16 +5,6 @@ include $(TOP)/configs/current
LIBNAME = i915_dri.so
DRIVER_SOURCES = \
i915_context.c \
i915_debug.c \
i915_fragprog.c \
i915_metaops.c \
i915_program.c \
i915_state.c \
i915_tex.c \
i915_texprog.c \
i915_texstate.c \
i915_vtbl.c \
i830_context.c \
i830_metaops.c \
i830_state.c \
@@ -22,16 +12,45 @@ DRIVER_SOURCES = \
i830_tex.c \
i830_texstate.c \
i830_vtbl.c \
intel_render.c \
intel_regions.c \
intel_buffer_objects.c \
intel_batchbuffer.c \
intel_mipmap_tree.c \
i915_tex_layout.c \
intel_tex_image.c \
intel_tex_subimage.c \
intel_tex_copy.c \
intel_tex_validate.c \
intel_tex_format.c \
intel_tex.c \
intel_pixel.c \
intel_pixel_copy.c \
intel_pixel_read.c \
intel_pixel_draw.c \
intel_buffers.c \
intel_blit.c \
i915_tex.c \
i915_texstate.c \
i915_context.c \
i915_debug.c \
i915_fragprog.c \
i915_metaops.c \
i915_program.c \
i915_state.c \
i915_texprog.c \
i915_vtbl.c \
intel_context.c \
intel_ioctl.c \
intel_pixel.c \
intel_render.c \
intel_screen.c \
intel_span.c \
intel_state.c \
intel_tex.c \
intel_tris.c
intel_tris.c \
intel_fbo.c \
intel_depthstencil.c \
intel_bufmgr.c
C_SOURCES = \
$(COMMON_SOURCES) \

View File

@@ -58,8 +58,8 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
void *sharedContextPrivate)
{
struct dd_function_table functions;
i830ContextPtr i830 = (i830ContextPtr) CALLOC_STRUCT(i830_context);
intelContextPtr intel = &i830->intel;
struct i830_context *i830 = CALLOC_STRUCT(i830_context);
struct intel_context *intel = &i830->intel;
GLcontext *ctx = &intel->ctx;
if (!i830) return GL_FALSE;
@@ -76,33 +76,14 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
intel->ctx.Const.MaxTextureImageUnits = I830_TEX_UNITS;
intel->ctx.Const.MaxTextureCoordUnits = I830_TEX_UNITS;
intel->nr_heaps = 1;
intel->texture_heaps[0] =
driCreateTextureHeap( 0, intel,
intel->intelScreen->tex.size,
12,
I830_NR_TEX_REGIONS,
intel->sarea->texList,
& intel->sarea->texAge,
& intel->swapped,
sizeof( struct i830_texture_object ),
(destroy_texture_object_t *)intelDestroyTexObj );
/* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
* FIXME: packed, but they're not in Intel graphics hardware.
/* Advertise the full hardware capabilities. The new memory
* manager should cope much better with overload situations:
*/
intel->ctx.Const.MaxTextureUnits = 1;
driCalculateMaxTextureLevels( intel->texture_heaps,
intel->nr_heaps,
&intel->ctx.Const,
4,
11, /* max 2D texture size is 2048x2048 */
8, /* max 3D texture size is 256^3 */
10, /* max CUBE texture size is 1024x1024 */
11, /* max RECT. supported */
12,
GL_FALSE );
intel->ctx.Const.MaxTextureUnits = I830_TEX_UNITS;
ctx->Const.MaxTextureLevels = 12;
ctx->Const.Max3DTextureLevels = 9;
ctx->Const.MaxCubeTextureLevels = 11;
ctx->Const.MaxTextureRectSize = (1<<11);
ctx->Const.MaxTextureUnits = I830_TEX_UNITS;
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
18 * sizeof(GLfloat) );
@@ -112,7 +93,7 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
driInitExtensions( ctx, i830_extensions, GL_FALSE );
i830InitState( i830 );
i830InitMetaFuncs( i830 );
_tnl_allow_vertex_fog( ctx, 1 );
_tnl_allow_pixel_fog( ctx, 0 );

View File

@@ -39,6 +39,7 @@
#define I830_UPLOAD_CTX 0x1
#define I830_UPLOAD_BUFFERS 0x2
#define I830_UPLOAD_STIPPLE 0x4
#define I830_UPLOAD_INVARIENT 0x8
#define I830_UPLOAD_TEX(i) (0x10<<(i))
#define I830_UPLOAD_TEXBLEND(i) (0x100<<(i))
#define I830_UPLOAD_TEX_ALL (0x0f0)
@@ -48,17 +49,15 @@
*/
#define I830_DESTREG_CBUFADDR0 0
#define I830_DESTREG_CBUFADDR1 1
#define I830_DESTREG_CBUFADDR2 2
#define I830_DESTREG_DBUFADDR0 3
#define I830_DESTREG_DBUFADDR1 4
#define I830_DESTREG_DBUFADDR2 5
#define I830_DESTREG_DV0 6
#define I830_DESTREG_DV1 7
#define I830_DESTREG_SENABLE 8
#define I830_DESTREG_SR0 9
#define I830_DESTREG_SR1 10
#define I830_DESTREG_SR2 11
#define I830_DEST_SETUP_SIZE 12
#define I830_DESTREG_DBUFADDR0 2
#define I830_DESTREG_DBUFADDR1 3
#define I830_DESTREG_DV0 4
#define I830_DESTREG_DV1 5
#define I830_DESTREG_SENABLE 6
#define I830_DESTREG_SR0 7
#define I830_DESTREG_SR1 8
#define I830_DESTREG_SR2 9
#define I830_DEST_SETUP_SIZE 10
#define I830_CTXREG_STATE1 0
#define I830_CTXREG_STATE2 1
@@ -84,14 +83,13 @@
#define I830_STP_SETUP_SIZE 2
#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
#define I830_TEXREG_TM0S0 1
#define I830_TEXREG_TM0S1 2
#define I830_TEXREG_TM0S2 3
#define I830_TEXREG_TM0S3 4
#define I830_TEXREG_TM0S4 5
#define I830_TEXREG_MCS 6 /* _3DSTATE_MAP_COORD_SETS */
#define I830_TEXREG_CUBE 7 /* _3DSTATE_MAP_SUBE */
#define I830_TEX_SETUP_SIZE 8
#define I830_TEXREG_TM0S1 1
#define I830_TEXREG_TM0S2 2
#define I830_TEXREG_TM0S3 3
#define I830_TEXREG_TM0S4 4
#define I830_TEXREG_MCS 5 /* _3DSTATE_MAP_COORD_SETS */
#define I830_TEXREG_CUBE 6 /* _3DSTATE_MAP_SUBE */
#define I830_TEX_SETUP_SIZE 7
#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */
@@ -110,6 +108,17 @@ struct i830_hw_state {
GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE];
GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE];
GLuint TexBlendWordsUsed[I830_TEX_UNITS];
struct intel_region *draw_region;
struct intel_region *depth_region;
/* Regions aren't actually that appropriate here as the memory may
* be from a PBO or FBO. Just use the buffer id. Will have to do
* this for draw and depth for FBO's...
*/
GLuint tex_buffer[I830_TEX_UNITS];
GLuint tex_offset[I830_TEX_UNITS];
GLuint emitted; /* I810_UPLOAD_* */
GLuint active;
};
@@ -118,15 +127,12 @@ struct i830_context
{
struct intel_context intel;
GLuint lodbias_tm0s3[MAX_TEXTURE_UNITS];
GLuint last_index;
struct i830_hw_state meta, initial, state, *current;
};
typedef struct i830_context *i830ContextPtr;
typedef struct i830_texture_object *i830TextureObjectPtr;
#define I830_CONTEXT(ctx) ((i830ContextPtr)(ctx))
@@ -148,7 +154,7 @@ do { \
/* i830_vtbl.c
*/
extern void
i830InitVtbl( i830ContextPtr i830 );
i830InitVtbl( struct i830_context *i830 );
/* i830_context.c
*/
@@ -160,22 +166,19 @@ i830CreateContext( const __GLcontextModes *mesaVis,
/* i830_tex.c, i830_texstate.c
*/
extern void
i830UpdateTextureState( intelContextPtr intel );
i830UpdateTextureState( struct intel_context *intel );
extern void
i830InitTextureFuncs( struct dd_function_table *functions );
extern intelTextureObjectPtr
i830AllocTexObj( struct gl_texture_object *tObj );
/* i830_texblend.c
*/
extern GLuint i830SetTexEnvCombine(i830ContextPtr i830,
extern GLuint i830SetTexEnvCombine(struct i830_context *i830,
const struct gl_tex_env_combine_state * combine, GLint blendUnit,
GLuint texel_op, GLuint *state, const GLfloat *factor );
extern void
i830EmitTextureBlend( i830ContextPtr i830 );
i830EmitTextureBlend( struct i830_context *i830 );
/* i830_state.c
@@ -184,32 +187,25 @@ extern void
i830InitStateFuncs( struct dd_function_table *functions );
extern void
i830EmitState( i830ContextPtr i830 );
i830EmitState( struct i830_context *i830 );
extern void
i830InitState( i830ContextPtr i830 );
i830InitState( struct i830_context *i830 );
/* i830_metaops.c
*/
extern GLboolean
i830TryTextureReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels );
extern GLboolean
i830TryTextureDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
extern void
i830ClearWithTris( intelContextPtr intel, GLbitfield mask,
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
i830InitMetaFuncs( struct i830_context *i830 );
/*======================================================================
* Inline conversion functions. These are better-typed than the
* macros used previously:
*/
static INLINE struct i830_context *
i830_context( GLcontext *ctx )
{
return (struct i830_context *)ctx;
}
#endif

View File

@@ -34,16 +34,18 @@
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_ioctl.h"
#include "intel_regions.h"
#include "i830_context.h"
#include "i830_reg.h"
/* A large amount of state doesn't need to be uploaded.
*/
#define ACTIVE (I830_UPLOAD_TEXBLEND(0) | \
I830_UPLOAD_STIPPLE | \
#define ACTIVE (I830_UPLOAD_INVARIENT | \
I830_UPLOAD_CTX | \
I830_UPLOAD_BUFFERS | \
I830_UPLOAD_STIPPLE | \
I830_UPLOAD_TEXBLEND(0) | \
I830_UPLOAD_TEX(0))
@@ -54,20 +56,11 @@ do { \
i830->current->emitted &= ~ACTIVE; \
} while (0)
/* Operations where the 3D engine is decoupled temporarily from the
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void set_initial_state( i830ContextPtr i830 )
{
memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
i830->meta.active = ACTIVE;
i830->meta.emitted = 0;
}
static void set_no_depth_stencil_write( i830ContextPtr i830 )
static void set_no_stencil_write( struct intel_context *intel )
{
struct i830_context *i830 = i830_context(&intel->ctx);
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
*/
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
@@ -75,6 +68,12 @@ static void set_no_depth_stencil_write( i830ContextPtr i830 )
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
i830->meta.emitted &= ~I830_UPLOAD_CTX;
}
static void set_no_depth_write( struct intel_context *intel )
{
struct i830_context *i830 = i830_context(&intel->ctx);
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
*/
@@ -86,25 +85,43 @@ static void set_no_depth_stencil_write( i830ContextPtr i830 )
i830->meta.emitted &= ~I830_UPLOAD_CTX;
}
/* Set depth unit to replace.
*/
static void set_depth_replace( struct intel_context *intel )
{
struct i830_context *i830 = i830_context(&intel->ctx);
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
* ctx->Driver.DepthMask( ctx, GL_TRUE )
*/
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE;
/* ctx->Driver.DepthFunc( ctx, GL_ALWAYS )
*/
i830->meta.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK;
i830->meta.Ctx[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC |
DEPTH_TEST_FUNC(COMPAREFUNC_ALWAYS));
i830->meta.emitted &= ~I830_UPLOAD_CTX;
}
/* Set stencil unit to replace always with the reference value.
*/
static void set_stencil_replace( i830ContextPtr i830,
static void set_stencil_replace( struct intel_context *intel,
GLuint s_mask,
GLuint s_clear)
{
struct i830_context *i830 = i830_context(&intel->ctx);
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
*/
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
*/
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
/* ctx->Driver.StencilMask( ctx, s_mask )
*/
i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
@@ -140,8 +157,10 @@ static void set_stencil_replace( i830ContextPtr i830,
}
static void set_color_mask( i830ContextPtr i830, GLboolean state )
static void set_color_mask( struct intel_context *intel, GLboolean state )
{
struct i830_context *i830 = i830_context(&intel->ctx);
const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
(1 << WRITEMASK_GREEN_SHIFT) |
(1 << WRITEMASK_BLUE_SHIFT) |
@@ -161,8 +180,9 @@ static void set_color_mask( i830ContextPtr i830, GLboolean state )
/* Installs a one-stage passthrough texture blend pipeline. Is there
* more that can be done to turn off texturing?
*/
static void set_no_texture( i830ContextPtr i830 )
static void set_no_texture( struct intel_context *intel )
{
struct i830_context *i830 = i830_context(&intel->ctx);
static const struct gl_tex_env_combine_state comb = {
GL_NONE, GL_NONE,
{ GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, },
@@ -181,13 +201,13 @@ static void set_no_texture( i830ContextPtr i830 )
/* Set up a single element blend stage for 'replace' texturing with no
* funny ops.
*/
static void enable_texture_blend_replace( i830ContextPtr i830,
GLenum format )
static void set_texture_blend_replace( struct intel_context *intel )
{
struct i830_context *i830 = i830_context(&intel->ctx);
static const struct gl_tex_env_combine_state comb = {
GL_REPLACE, GL_REPLACE,
{ GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, },
{ GL_SRC_COLOR, 0, 0 }, { GL_SRC_ALPHA, 0, 0 },
{ GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, }, { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, },
{ GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR }, { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
0, 0, 1, 1
};
@@ -207,31 +227,90 @@ static void enable_texture_blend_replace( i830ContextPtr i830,
/* Set up an arbitary piece of memory as a rectangular texture
* (including the front or back buffer).
*/
static void set_tex_rect_source( i830ContextPtr i830,
GLuint offset,
GLuint width,
GLuint height,
GLuint pitch,
GLuint textureFormat )
static GLboolean set_tex_rect_source( struct intel_context *intel,
GLuint buffer,
GLuint offset,
GLuint pitch,
GLuint height,
GLenum format,
GLenum type)
{
GLint numLevels = 1;
struct i830_context *i830 = i830_context(&intel->ctx);
GLuint *setup = i830->meta.Tex[0];
GLint numLevels = 1;
GLuint textureFormat;
GLuint cpp;
pitch *= i830->intel.intelScreen->cpp;
/* A full implementation of this would do the upload through
* glTexImage2d, and get all the conversion operations at that
* point. We are restricted, but still at least have access to the
* fragment program swizzle.
*/
switch (format) {
case GL_BGRA:
switch (type) {
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_BYTE:
textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888);
cpp = 4;
break;
default:
return GL_FALSE;
}
break;
case GL_RGBA:
switch (type) {
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_BYTE:
textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888);
cpp = 4;
break;
default:
return GL_FALSE;
}
break;
case GL_BGR:
switch (type) {
case GL_UNSIGNED_SHORT_5_6_5_REV:
textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
cpp = 2;
break;
default:
return GL_FALSE;
}
break;
case GL_RGB:
switch (type) {
case GL_UNSIGNED_SHORT_5_6_5:
textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
cpp = 2;
break;
default:
return GL_FALSE;
}
break;
/* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
/* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
default:
return GL_FALSE;
}
i830->meta.tex_buffer[0] = buffer;
i830->meta.tex_offset[0] = offset;
setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
(LOAD_TEXTURE_MAP0 << 0) | 4);
setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset);
setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
((width - 1) << TM0S1_WIDTH_SHIFT) |
((pitch - 1) << TM0S1_WIDTH_SHIFT) |
textureFormat);
setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));
setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
setup[I830_TEXREG_TM0S2] = (((((pitch * cpp) / 4) - 1) << TM0S2_PITCH_SHIFT) |
TM0S2_CUBE_FACE_ENA_MASK);
setup[I830_TEXREG_TM0S3] = ( (((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT) |
(FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT) |
(MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT) |
(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT));
setup[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(0));
setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
MAP_UNIT(0) |
@@ -244,40 +323,17 @@ static void set_tex_rect_source( i830ContextPtr i830,
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
return GL_TRUE;
}
/* Select between front and back draw buffers.
*/
static void set_draw_offset( i830ContextPtr i830,
GLuint offset )
{
i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset;
i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
}
/* Setup an arbitary draw format, useful for targeting
* texture or agp memory.
*/
static void set_draw_format( i830ContextPtr i830,
GLuint format,
GLuint depth_format)
{
i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
format |
DEPTH_IS_Z |
depth_format);
}
static void set_vertex_format( i830ContextPtr i830 )
static void set_vertex_format( struct intel_context *intel )
{
struct i830_context *i830 = i830_context(&intel->ctx);
i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
VFT0_TEX_COUNT(1) |
VFT0_DIFFUSE |
VFT0_SPEC |
VFT0_XYZW);
VFT0_XYZ);
i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD |
VFT1_TEX0_FMT(TEXCOORDFMT_2D) |
VFT1_TEX1_FMT(TEXCOORDFMT_2D) |
@@ -287,446 +343,127 @@ static void set_vertex_format( i830ContextPtr i830 )
}
static void draw_quad(i830ContextPtr i830,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1 )
static void meta_import_pixel_state( struct intel_context *intel )
{
GLuint vertex_size = 8;
GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
PRIM3D_TRIFAN,
4*vertex_size,
vertex_size );
intelVertex tmp;
int i;
struct i830_context *i830 = i830_context(&intel->ctx);
i830->meta.Ctx[I830_CTXREG_STATE1] = i830->state.Ctx[I830_CTXREG_STATE1];
i830->meta.Ctx[I830_CTXREG_STATE2] = i830->state.Ctx[I830_CTXREG_STATE2];
i830->meta.Ctx[I830_CTXREG_STATE3] = i830->state.Ctx[I830_CTXREG_STATE3];
i830->meta.Ctx[I830_CTXREG_STATE4] = i830->state.Ctx[I830_CTXREG_STATE4];
i830->meta.Ctx[I830_CTXREG_STATE5] = i830->state.Ctx[I830_CTXREG_STATE5];
i830->meta.Ctx[I830_CTXREG_IALPHAB] = i830->state.Ctx[I830_CTXREG_IALPHAB];
i830->meta.Ctx[I830_CTXREG_STENCILTST] = i830->state.Ctx[I830_CTXREG_STENCILTST];
i830->meta.Ctx[I830_CTXREG_ENABLES_1] = i830->state.Ctx[I830_CTXREG_ENABLES_1];
i830->meta.Ctx[I830_CTXREG_ENABLES_2] = i830->state.Ctx[I830_CTXREG_ENABLES_2];
i830->meta.Ctx[I830_CTXREG_AA] = i830->state.Ctx[I830_CTXREG_AA];
i830->meta.Ctx[I830_CTXREG_FOGCOLOR] = i830->state.Ctx[I830_CTXREG_FOGCOLOR];
i830->meta.Ctx[I830_CTXREG_BLENDCOLOR0] = i830->state.Ctx[I830_CTXREG_BLENDCOLOR0];
i830->meta.Ctx[I830_CTXREG_BLENDCOLOR1] = i830->state.Ctx[I830_CTXREG_BLENDCOLOR1];
i830->meta.Ctx[I830_CTXREG_MCSB0] = i830->state.Ctx[I830_CTXREG_MCSB0];
i830->meta.Ctx[I830_CTXREG_MCSB1] = i830->state.Ctx[I830_CTXREG_MCSB1];
/* fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
/* __FUNCTION__, */
/* x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
i830->meta.Ctx[I830_CTXREG_STATE3] &= ~CULLMODE_MASK;
i830->meta.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE;
i830->meta.emitted &= ~I830_UPLOAD_CTX;
/* initial vertex, left bottom */
tmp.v.x = x0;
tmp.v.y = y0;
tmp.v.z = 1.0;
tmp.v.w = 1.0;
tmp.v.color.red = red;
tmp.v.color.green = green;
tmp.v.color.blue = blue;
tmp.v.color.alpha = alpha;
tmp.v.specular.red = 0;
tmp.v.specular.green = 0;
tmp.v.specular.blue = 0;
tmp.v.specular.alpha = 0;
tmp.v.u0 = s0;
tmp.v.v0 = t0;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* right bottom */
vb += 8;
tmp.v.x = x1;
tmp.v.u0 = s1;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* right top */
vb += 8;
tmp.v.y = y1;
tmp.v.v0 = t1;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* left top */
vb += 8;
tmp.v.x = x0;
tmp.v.u0 = s0;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* fprintf(stderr, "%s: DV1: %x\n", */
/* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
}
void
i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
{
i830ContextPtr i830 = I830_CONTEXT( intel );
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelScreenPrivate *screen = intel->intelScreen;
int x0, y0, x1, y1;
SET_STATE( i830, meta );
set_initial_state( i830 );
set_no_texture( i830 );
set_vertex_format( i830 );
LOCK_HARDWARE(intel);
if(!all) {
x0 = cx;
y0 = cy;
x1 = x0 + cw;
y1 = y0 + ch;
} else {
x0 = 0;
y0 = 0;
x1 = x0 + dPriv->w;
y1 = y0 + dPriv->h;
}
/* Don't do any clipping to screen - these are window coordinates.
* The active cliprects will be applied as for any other geometry.
*/
if(mask & BUFFER_BIT_FRONT_LEFT) {
set_no_depth_stencil_write( i830 );
set_color_mask( i830, GL_TRUE );
set_draw_offset( i830, screen->front.offset );
draw_quad(i830, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if(mask & BUFFER_BIT_BACK_LEFT) {
set_no_depth_stencil_write( i830 );
set_color_mask( i830, GL_TRUE );
set_draw_offset( i830, screen->back.offset );
draw_quad(i830, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if(mask & BUFFER_BIT_STENCIL) {
set_stencil_replace( i830,
intel->ctx.Stencil.WriteMask[0],
intel->ctx.Stencil.Clear);
set_color_mask( i830, GL_FALSE );
set_draw_offset( i830, screen->front.offset );
draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
}
UNLOCK_HARDWARE(intel);
SET_STATE( i830, state );
i830->meta.Buffer[I830_DESTREG_SENABLE] = i830->state.Buffer[I830_DESTREG_SENABLE];
i830->meta.Buffer[I830_DESTREG_SR1] = i830->state.Buffer[I830_DESTREG_SR1];
i830->meta.Buffer[I830_DESTREG_SR2] = i830->state.Buffer[I830_DESTREG_SR2];
i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
}
GLboolean
i830TryTextureReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
/* Select between front and back draw buffers.
*/
static void meta_draw_region( struct intel_context *intel,
struct intel_region *draw_region,
struct intel_region *depth_region )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *screen = i830->intel.intelScreen;
GLint pitch = pack->RowLength ? pack->RowLength : width;
__DRIdrawablePrivate *dPriv = i830->intel.driDrawable;
int textureFormat;
GLenum glTextureFormat;
int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels);
int destFormat, depthFormat, destPitch;
drm_clip_rect_t tmp;
struct i830_context *i830 = i830_context(&intel->ctx);
GLuint format;
GLuint depth_format = DEPTH_FRMT_16_FIXED;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( ctx->_ImageTransferState ||
pack->SwapBytes ||
pack->LsbFirst ||
!pack->Invert) {
fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
return GL_FALSE;
}
switch (screen->fbFormat) {
case DV_PF_565:
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
glTextureFormat = GL_RGB;
break;
case DV_PF_555:
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
glTextureFormat = GL_RGBA;
break;
case DV_PF_8888:
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
glTextureFormat = GL_RGBA;
break;
default:
fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__,
screen->fbFormat);
return GL_FALSE;
}
switch (type) {
case GL_UNSIGNED_SHORT_5_6_5:
if (format != GL_RGB) return GL_FALSE;
destFormat = COLR_BUF_RGB565;
depthFormat = DEPTH_FRMT_16_FIXED;
destPitch = pitch * 2;
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
if (format != GL_BGRA) return GL_FALSE;
destFormat = COLR_BUF_ARGB8888;
depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER;
destPitch = pitch * 4;
break;
default:
fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(type));
return GL_FALSE;
}
destFormat |= (0x02<<24);
/* fprintf(stderr, "type: %s destFormat: %x\n", */
/* _mesa_lookup_enum_by_nr(type), */
/* destFormat); */
intelFlush( ctx );
SET_STATE( i830, meta );
set_initial_state( i830 );
set_no_depth_stencil_write( i830 );
LOCK_HARDWARE( intel );
{
intelWaitForIdle( intel ); /* required by GL */
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
return GL_TRUE;
}
#if 0
/* FIXME -- Just emit the correct state
*/
if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,
destPitch) != 0) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: setparam failed\n", __FUNCTION__);
return GL_FALSE;
}
#endif
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
/* Set the frontbuffer up as a large rectangular texture.
*/
set_tex_rect_source( i830,
src_offset,
screen->width,
screen->height,
screen->front.pitch,
textureFormat );
intel_region_release(intel, &i830->meta.draw_region);
intel_region_reference(&i830->meta.draw_region, draw_region);
enable_texture_blend_replace( i830, glTextureFormat );
intel_region_release(intel, &i830->meta.depth_region);
intel_region_reference(&i830->meta.depth_region, depth_region);
/* XXX FBO: grab code from i915 meta_draw_region */
/* Set the 3d engine to draw into the agp memory
*/
/* XXX: 555 support?
*/
if (draw_region->cpp == 2)
format = DV_PF_565;
else
format = DV_PF_8888;
set_draw_offset( i830, destOffset );
set_draw_format( i830, destFormat, depthFormat );
/* Draw a single quad, no cliprects:
*/
i830->intel.numClipRects = 1;
i830->intel.pClipRects = &tmp;
i830->intel.pClipRects[0].x1 = 0;
i830->intel.pClipRects[0].y1 = 0;
i830->intel.pClipRects[0].x2 = width;
i830->intel.pClipRects[0].y2 = height;
draw_quad( i830,
0, width, 0, height,
0, 255, 0, 0,
x, x+width, y, y+height );
intelWindowMoved( intel );
if (depth_region) {
if (depth_region->cpp == 2)
depth_format = DEPTH_FRMT_16_FIXED;
else
depth_format = DEPTH_FRMT_24_FIXED_8_OTHER;
}
UNLOCK_HARDWARE( intel );
intelFinish( ctx ); /* required by GL */
SET_STATE( i830, state );
return GL_TRUE;
i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
format |
DEPTH_IS_Z |
depth_format);
i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
}
GLboolean
i830TryTextureDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
/* Operations where the 3D engine is decoupled temporarily from the
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void install_meta_state( struct intel_context *intel )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
i830ContextPtr i830 = I830_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int textureFormat;
GLenum glTextureFormat;
int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
int src_offset = intelAgpOffsetFromVirtual( intel, pixels );
struct i830_context *i830 = i830_context(&intel->ctx);
memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
i830->meta.active = ACTIVE;
i830->meta.emitted = 0;
/* Todo -- upload images that aren't in agp space, then texture
* from them.
*/
SET_STATE(i830, meta);
set_vertex_format(intel);
set_no_texture(intel);
}
if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) {
fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__);
return GL_FALSE;
}
/* Todo -- don't want to clobber all the drawing state like we do
* for readpixels -- most of this state can be handled just fine.
*/
if ( ctx->_ImageTransferState ||
unpack->SwapBytes ||
unpack->LsbFirst ||
ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits) {
fprintf(stderr, "%s: other tests failed\n", __FUNCTION__);
return GL_FALSE;
}
/* Todo -- remove these restrictions:
*/
if (ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != -1.0F)
return GL_FALSE;
switch (type) {
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
if (format != GL_BGRA) return GL_FALSE;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
glTextureFormat = GL_RGBA;
break;
case GL_UNSIGNED_SHORT_5_6_5:
if (format != GL_RGB) return GL_FALSE;
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
glTextureFormat = GL_RGB;
break;
case GL_UNSIGNED_SHORT_8_8_MESA:
if (format != GL_YCBCR_MESA) return GL_FALSE;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY
/* | TM0S1_COLORSPACE_CONVERSION */
);
glTextureFormat = GL_YCBCR_MESA;
break;
case GL_UNSIGNED_SHORT_8_8_REV_MESA:
if (format != GL_YCBCR_MESA) return GL_FALSE;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL
/* | TM0S1_COLORSPACE_CONVERSION */
);
glTextureFormat = GL_YCBCR_MESA;
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
if (format != GL_BGRA) return GL_FALSE;
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
glTextureFormat = GL_RGBA;
break;
default:
fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__);
return GL_FALSE;
}
intelFlush( ctx );
SET_STATE( i830, meta );
LOCK_HARDWARE( intel );
{
intelWaitForIdle( intel ); /* required by GL */
y -= height; /* cope with pixel zoom */
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
return GL_TRUE;
}
y = dPriv->h - y - height;
set_initial_state( i830 );
/* Set the pixel image up as a rectangular texture.
*/
set_tex_rect_source( i830,
src_offset,
width,
height,
pitch, /* XXXX!!!! -- /2 sometimes */
textureFormat );
enable_texture_blend_replace( i830, glTextureFormat );
/* Draw to the current draw buffer:
*/
set_draw_offset( i830, dst_offset );
/* Draw a quad, use regular cliprects
*/
/* fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
draw_quad( i830,
x, x+width, y, y+height,
0, 255, 0, 0,
0, width, 0, height );
intelWindowMoved( intel );
}
UNLOCK_HARDWARE( intel );
intelFinish( ctx ); /* required by GL */
static void leave_meta_state( struct intel_context *intel )
{
struct i830_context *i830 = i830_context(&intel->ctx);
intel_region_release(intel, &i830->meta.draw_region);
intel_region_release(intel, &i830->meta.depth_region);
/* intel_region_release(intel, &i830->meta.tex_region[0]); */
SET_STATE(i830, state);
return GL_TRUE;
}
void i830InitMetaFuncs( struct i830_context *i830 )
{
i830->intel.vtbl.install_meta_state = install_meta_state;
i830->intel.vtbl.leave_meta_state = leave_meta_state;
i830->intel.vtbl.meta_no_depth_write = set_no_depth_write;
i830->intel.vtbl.meta_no_stencil_write = set_no_stencil_write;
i830->intel.vtbl.meta_stencil_replace = set_stencil_replace;
i830->intel.vtbl.meta_depth_replace = set_depth_replace;
i830->intel.vtbl.meta_color_mask = set_color_mask;
i830->intel.vtbl.meta_no_texture = set_no_texture;
i830->intel.vtbl.meta_texture_blend_replace = set_texture_blend_replace;
i830->intel.vtbl.meta_tex_rect_source = set_tex_rect_source;
i830->intel.vtbl.meta_draw_region = meta_draw_region;
i830->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state;
}

View File

@@ -407,10 +407,10 @@
#define LOGICOP_SET 0xf
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
#define ENABLE_STENCIL_TEST_MASK (1<<17)
#define STENCIL_TEST_MASK(x) ((x)<<8)
#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8)
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
#define ENABLE_STENCIL_WRITE_MASK (1<<16)
#define STENCIL_WRITE_MASK(x) (x)
#define STENCIL_WRITE_MASK(x) ((x)&0xff)
/* _3DSTATE_MODES_5, p196 */
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))

View File

@@ -36,6 +36,7 @@
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_fbo.h"
#include "i830_context.h"
#include "i830_reg.h"
@@ -44,7 +45,7 @@ static void
i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
GLuint mask)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
int test = intel_translate_compare_func(func);
mask = mask & 0xff;
@@ -69,7 +70,7 @@ i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
static void
i830StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
if (INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask);
@@ -86,7 +87,7 @@ static void
i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
GLenum zpass)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
int fop, dfop, dpop;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -193,7 +194,7 @@ i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
int test = intel_translate_compare_func(func);
GLubyte refByte;
GLuint refInt;
@@ -221,7 +222,7 @@ static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
*/
static void i830EvalLogicOpBlendState(GLcontext *ctx)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
@@ -245,7 +246,7 @@ static void i830EvalLogicOpBlendState(GLcontext *ctx)
static void i830BlendColor(GLcontext *ctx, const GLfloat color[4])
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
GLubyte r, g, b, a;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -268,7 +269,7 @@ static void i830BlendColor(GLcontext *ctx, const GLfloat color[4])
*/
static void i830_set_blend_state( GLcontext * ctx )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
int funcA;
int funcRGB;
int eqnA;
@@ -406,7 +407,7 @@ static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
static void i830DepthFunc(GLcontext *ctx, GLenum func)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
int test = intel_translate_compare_func(func);
if (INTEL_DEBUG&DEBUG_DRI)
@@ -420,7 +421,7 @@ static void i830DepthFunc(GLcontext *ctx, GLenum func)
static void i830DepthMask(GLcontext *ctx, GLboolean flag)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
if (INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag);
@@ -443,7 +444,7 @@ static void i830DepthMask(GLcontext *ctx, GLboolean flag)
*/
static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
const GLubyte *m = mask;
GLubyte p[4];
int i,j,k;
@@ -496,15 +497,14 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
static void i830Scissor(GLcontext *ctx, GLint x, GLint y,
GLsizei w, GLsizei h)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
intelScreenPrivate *screen = i830->intel.intelScreen;
struct i830_context *i830 = i830_context(ctx);
int x1, y1, x2, y2;
if (!i830->intel.driDrawable)
if (!ctx->DrawBuffer)
return;
x1 = x;
y1 = i830->intel.driDrawable->h - (y + h);
y1 = ctx->DrawBuffer->Height - (y + h);
x2 = x + w - 1;
y2 = y1 + h - 1;
@@ -512,16 +512,10 @@ static void i830Scissor(GLcontext *ctx, GLint x, GLint y,
fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
x, y, w, h);
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
if (x2 < 0) x2 = 0;
if (y2 < 0) y2 = 0;
if (x2 >= screen->width) x2 = screen->width-1;
if (y2 >= screen->height) y2 = screen->height-1;
if (x1 >= screen->width) x1 = screen->width-1;
if (y1 >= screen->height) y1 = screen->height-1;
x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1);
y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1);
x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1);
y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1);
I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
i830->state.Buffer[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
@@ -530,7 +524,7 @@ static void i830Scissor(GLcontext *ctx, GLint x, GLint y,
static void i830LogicOp(GLcontext *ctx, GLenum opcode)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
int tmp = intel_translate_logic_op( opcode );
if (INTEL_DEBUG&DEBUG_DRI)
@@ -545,7 +539,7 @@ static void i830LogicOp(GLcontext *ctx, GLenum opcode)
static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
GLuint mode;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -573,7 +567,7 @@ static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused)
static void i830LineWidth( GLcontext *ctx, GLfloat widthf )
{
i830ContextPtr i830 = I830_CONTEXT( ctx );
struct i830_context *i830 = i830_context( ctx );
int width;
int state5;
@@ -594,7 +588,7 @@ static void i830LineWidth( GLcontext *ctx, GLfloat widthf )
static void i830PointSize(GLcontext *ctx, GLfloat size)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
GLint point_size = (int)size;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -616,7 +610,7 @@ static void i830ColorMask(GLcontext *ctx,
GLboolean r, GLboolean g,
GLboolean b, GLboolean a)
{
i830ContextPtr i830 = I830_CONTEXT( ctx );
struct i830_context *i830 = i830_context( ctx );
GLuint tmp = 0;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -638,7 +632,7 @@ static void i830ColorMask(GLcontext *ctx,
static void update_specular( GLcontext *ctx )
{
i830ContextPtr i830 = I830_CONTEXT( ctx );
struct i830_context *i830 = i830_context( ctx );
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK;
@@ -664,7 +658,7 @@ static void i830LightModelfv(GLcontext *ctx, GLenum pname,
*/
static void i830ShadeModel(GLcontext *ctx, GLenum mode)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
@@ -690,7 +684,7 @@ static void i830ShadeModel(GLcontext *ctx, GLenum mode)
*/
static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
if (INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s\n", __FUNCTION__);
@@ -710,7 +704,7 @@ static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct i830_context *i830 = i830_context(ctx);
switch(cap) {
case GL_LIGHTING:
@@ -806,20 +800,28 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
break;
case GL_STENCIL_TEST:
if (i830->intel.hw_stencil) {
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
{
GLboolean hw_stencil = GL_FALSE;
if (ctx->DrawBuffer) {
struct intel_renderbuffer *irbStencil
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
hw_stencil = (irbStencil && irbStencil->region);
}
if (hw_stencil) {
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
if (state) {
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
} else {
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
}
} else {
FALLBACK( &i830->intel, I830_FALLBACK_STENCIL, state );
if (state) {
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
} else {
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
}
} else {
FALLBACK( &i830->intel, I830_FALLBACK_STENCIL, state );
}
}
break;
@@ -844,7 +846,7 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
}
static void i830_init_packets( i830ContextPtr i830 )
static void i830_init_packets( struct i830_context *i830 )
{
intelScreenPrivate *screen = i830->intel.intelScreen;
@@ -902,6 +904,7 @@ static void i830_init_packets( i830ContextPtr i830 )
DISABLE_COLOR_BLEND |
DISABLE_DEPTH_TEST);
#if 000 /* XXX all the stencil enable state is set in i830Enable(), right? */
if (i830->intel.hw_stencil) {
i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD |
ENABLE_STENCIL_WRITE |
@@ -911,7 +914,9 @@ static void i830_init_packets( i830ContextPtr i830 )
/* set no color comps disabled */
ENABLE_COLOR_WRITE |
ENABLE_DEPTH_WRITE);
} else {
} else
#endif
{
i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD |
DISABLE_STENCIL_WRITE |
ENABLE_TEX_CACHE |
@@ -1010,15 +1015,14 @@ static void i830_init_packets( i830ContextPtr i830 )
i830->state.Buffer[I830_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
i830->state.Buffer[I830_DESTREG_DBUFADDR1] =
(BUF_3D_ID_DEPTH |
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) |
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | /* XXX FBO fix */
BUF_3D_USE_FENCE);
i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset;
/* i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; */
i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
switch (screen->fbFormat) {
case DV_PF_555:
case DV_PF_565:
i830->state.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
@@ -1068,7 +1072,7 @@ void i830InitStateFuncs( struct dd_function_table *functions )
functions->StencilOpSeparate = i830StencilOpSeparate;
}
void i830InitState( i830ContextPtr i830 )
void i830InitState( struct i830_context *i830 )
{
GLcontext *ctx = &i830->intel.ctx;
@@ -1080,7 +1084,8 @@ void i830InitState( i830ContextPtr i830 )
i830->current = &i830->state;
i830->state.emitted = 0;
i830->state.active = (I830_UPLOAD_TEXBLEND(0) |
i830->state.active = (I830_UPLOAD_INVARIENT |
I830_UPLOAD_TEXBLEND(0) |
I830_UPLOAD_STIPPLE |
I830_UPLOAD_CTX |
I830_UPLOAD_BUFFERS);

View File

@@ -45,261 +45,12 @@
/**
* Set the texture wrap modes.
*
* The i830M (and related graphics cores) do not support GL_CLAMP. The Intel
* drivers for "other operating systems" implement GL_CLAMP as
* GL_CLAMP_TO_EDGE, so the same is done here.
*
* \param t Texture object whose wrap modes are to be set
* \param swrap Wrap mode for the \a s texture coordinate
* \param twrap Wrap mode for the \a t texture coordinate
*/
static void i830SetTexWrapping(i830TextureObjectPtr tex,
GLenum swrap,
GLenum twrap)
{
tex->Setup[I830_TEXREG_MCS] &= ~(TEXCOORD_ADDR_U_MASK|TEXCOORD_ADDR_V_MASK);
switch( swrap ) {
case GL_REPEAT:
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP);
break;
case GL_CLAMP:
case GL_CLAMP_TO_EDGE:
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP);
break;
case GL_CLAMP_TO_BORDER:
tex->Setup[I830_TEXREG_MCS] |=
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER);
break;
case GL_MIRRORED_REPEAT:
tex->Setup[I830_TEXREG_MCS] |=
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR);
break;
default:
break;
}
switch( twrap ) {
case GL_REPEAT:
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP);
break;
case GL_CLAMP:
case GL_CLAMP_TO_EDGE:
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP);
break;
case GL_CLAMP_TO_BORDER:
tex->Setup[I830_TEXREG_MCS] |=
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER);
break;
case GL_MIRRORED_REPEAT:
tex->Setup[I830_TEXREG_MCS] |=
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR);
break;
default:
break;
}
}
/**
* Set the texture magnification and minification modes.
*
* \param t Texture whose filter modes are to be set
* \param minf Texture minification mode
* \param magf Texture magnification mode
* \param bias LOD bias for this texture unit.
*/
static void i830SetTexFilter( i830TextureObjectPtr t, GLenum minf, GLenum magf,
GLfloat maxanisotropy )
{
int minFilt = 0, mipFilt = 0, magFilt = 0;
if(INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( maxanisotropy > 1.0 ) {
minFilt = FILTER_ANISOTROPIC;
magFilt = FILTER_ANISOTROPIC;
}
else {
switch (minf) {
case GL_NEAREST:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_NONE;
break;
case GL_LINEAR:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_NONE;
break;
case GL_NEAREST_MIPMAP_NEAREST:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_NEAREST;
break;
case GL_LINEAR_MIPMAP_NEAREST:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_LINEAR;
break;
case GL_LINEAR_MIPMAP_LINEAR:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_LINEAR;
break;
default:
break;
}
switch (magf) {
case GL_NEAREST:
magFilt = FILTER_NEAREST;
break;
case GL_LINEAR:
magFilt = FILTER_LINEAR;
break;
default:
break;
}
}
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_FILTER_MASK;
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIP_FILTER_MASK;
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAG_FILTER_MASK;
t->Setup[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
(mipFilt << TM0S3_MIP_FILTER_SHIFT) |
(magFilt << TM0S3_MAG_FILTER_SHIFT));
}
static void i830SetTexBorderColor(i830TextureObjectPtr t, GLubyte color[4])
{
if(INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s\n", __FUNCTION__);
t->Setup[I830_TEXREG_TM0S4] =
INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3]);
}
/**
* Allocate space for and load the mesa images into the texture memory block.
* This will happen before drawing with a new texture, or drawing with a
* texture after it was swapped out or teximaged again.
*/
intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj )
{
i830TextureObjectPtr t = CALLOC_STRUCT( i830_texture_object );
if ( !t )
return NULL;
texObj->DriverData = t;
t->intel.base.tObj = texObj;
t->intel.dirty = I830_UPLOAD_TEX_ALL;
make_empty_list( &t->intel.base );
t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */
t->Setup[I830_TEXREG_TM0S0] = 0;
t->Setup[I830_TEXREG_TM0S1] = 0;
t->Setup[I830_TEXREG_TM0S2] = 0;
t->Setup[I830_TEXREG_TM0S3] = 0;
t->Setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
MAP_UNIT(0) |
ENABLE_TEXCOORD_PARAMS |
TEXCOORDS_ARE_NORMAL |
TEXCOORDTYPE_CARTESIAN |
ENABLE_ADDR_V_CNTL |
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
ENABLE_ADDR_U_CNTL |
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
i830SetTexWrapping( t, texObj->WrapS, texObj->WrapT );
i830SetTexFilter( t, texObj->MinFilter, texObj->MagFilter,
texObj->MaxAnisotropy );
i830SetTexBorderColor( t, texObj->_BorderChan );
return &t->intel;
}
static void i830TexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
if (!t)
return;
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
i830SetTexFilter( t, tObj->MinFilter, tObj->MagFilter,
tObj->MaxAnisotropy);
break;
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
i830SetTexWrapping( t, tObj->WrapS, tObj->WrapT );
break;
case GL_TEXTURE_BORDER_COLOR:
i830SetTexBorderColor( t, tObj->_BorderChan );
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* The i830 and its successors can do a lot of this without
* reloading the textures. A project for someone?
*/
intelFlush( ctx );
driSwapOutTextureObject( (driTextureObject *) t );
break;
default:
return;
}
t->intel.dirty = I830_UPLOAD_TEX_ALL;
}
static void i830TexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
i830ContextPtr i830 = I830_CONTEXT( ctx );
GLuint unit = ctx->Texture.CurrentUnit;
switch (pname) {
case GL_TEXTURE_ENV_COLOR:
#if 0
{
GLubyte r, g, b, a;
GLuint col;
UNCLAMPED_FLOAT_TO_UBYTE(r, param[RCOMP]);
UNCLAMPED_FLOAT_TO_UBYTE(g, param[GCOMP]);
UNCLAMPED_FLOAT_TO_UBYTE(b, param[BCOMP]);
UNCLAMPED_FLOAT_TO_UBYTE(a, param[ACOMP]);
col = ((a << 24) | (r << 16) | (g << 8) | b);
if (col != i830->state.TexEnv[unit][I830_TEXENVREG_COL1]) {
I830_STATECHANGE(i830, I830_UPLOAD_TEXENV);
i830->state.TexEnv[unit][I830_TEXENVREG_COL1] = col;
}
break;
}
#endif
case GL_TEXTURE_ENV_MODE:
case GL_COMBINE_RGB:
case GL_COMBINE_ALPHA:
@@ -320,13 +71,13 @@ static void i830TexEnv( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_LOD_BIAS: {
struct i830_context *i830 = i830_context( ctx );
GLuint unit = ctx->Texture.CurrentUnit;
int b = (int) ((*param) * 16.0);
if (b > 63) b = 63;
if (b < -64) b = -64;
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
i830->state.Tex[unit][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK;
i830->state.Tex[unit][I830_TEXREG_TM0S3] |=
((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
i830->lodbias_tm0s3[unit] = ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
break;
}
@@ -341,5 +92,4 @@ static void i830TexEnv( GLcontext *ctx, GLenum target,
void i830InitTextureFuncs( struct dd_function_table *functions )
{
functions->TexEnv = i830TexEnv;
functions->TexParameter = i830TexParameter;
}

View File

@@ -101,7 +101,7 @@ static GLuint emit_factor( GLuint blendUnit, GLuint *state, GLuint count,
}
static __inline__ GLuint GetTexelOp(GLint unit)
static INLINE GLuint GetTexelOp(GLint unit)
{
switch(unit) {
case 0: return TEXBLENDARG_TEXEL0;
@@ -132,7 +132,7 @@ static __inline__ GLuint GetTexelOp(GLint unit)
* partial support for the extension?
*/
GLuint
i830SetTexEnvCombine(i830ContextPtr i830,
i830SetTexEnvCombine(struct i830_context *i830,
const struct gl_tex_env_combine_state * combine,
GLint blendUnit,
GLuint texel_op,
@@ -394,7 +394,7 @@ i830SetTexEnvCombine(i830ContextPtr i830,
}
static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit,
static void emit_texblend( struct i830_context *i830, GLuint unit, GLuint blendUnit,
GLboolean last_stage )
{
struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit];
@@ -423,7 +423,7 @@ static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit,
I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(blendUnit), GL_TRUE);
}
static void emit_passthrough( i830ContextPtr i830 )
static void emit_passthrough( struct i830_context *i830 )
{
GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
GLuint unit = 0;
@@ -442,7 +442,7 @@ static void emit_passthrough( i830ContextPtr i830 )
I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(unit), GL_TRUE);
}
void i830EmitTextureBlend( i830ContextPtr i830 )
void i830EmitTextureBlend( struct i830_context *i830 )
{
GLcontext *ctx = &i830->intel.ctx;
GLuint unit, last_stage = 0, blendunit = 0;

View File

@@ -38,441 +38,274 @@
#include "intel_screen.h"
#include "intel_ioctl.h"
#include "intel_tex.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "i830_context.h"
#include "i830_reg.h"
static const GLint initial_offsets[6][2] = { {0,0},
{0,2},
{1,0},
{1,2},
{1,1},
{1,3} };
static const GLint step_offsets[6][2] = { {0,2},
{0,2},
{-1,2},
{-1,2},
{-1,1},
{-1,1} };
#define I830_TEX_UNIT_ENABLED(unit) (1<<unit)
static GLboolean i830SetTexImages( i830ContextPtr i830,
struct gl_texture_object *tObj )
static GLuint translate_texture_format( GLuint mesa_format )
{
GLuint total_height, pitch, i, textureFormat;
i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
GLint firstLevel, lastLevel, numLevels;
switch( baseImage->TexFormat->MesaFormat ) {
switch (mesa_format) {
case MESA_FORMAT_L8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
break;
return MAPSURF_8BIT | MT_8BIT_L8;
case MESA_FORMAT_I8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
break;
return MAPSURF_8BIT | MT_8BIT_I8;
case MESA_FORMAT_A8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_I8; /* Kludge -- check with conform, glean */
break;
return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */
case MESA_FORMAT_AL88:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
break;
return MAPSURF_16BIT | MT_16BIT_AY88;
case MESA_FORMAT_RGB565:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
break;
return MAPSURF_16BIT | MT_16BIT_RGB565;
case MESA_FORMAT_ARGB1555:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
break;
return MAPSURF_16BIT | MT_16BIT_ARGB1555;
case MESA_FORMAT_ARGB4444:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
break;
return MAPSURF_16BIT | MT_16BIT_ARGB4444;
case MESA_FORMAT_ARGB8888:
t->intel.texelBytes = 4;
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
break;
return MAPSURF_32BIT | MT_32BIT_ARGB8888;
case MESA_FORMAT_YCBCR_REV:
t->intel.texelBytes = 2;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL |
TM0S1_COLORSPACE_CONVERSION);
break;
return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
case MESA_FORMAT_YCBCR:
t->intel.texelBytes = 2;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */
TM0S1_COLORSPACE_CONVERSION);
break;
return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_COMPRESSED | MT_COMPRESS_FXT1;
break;
return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
case MESA_FORMAT_RGBA_DXT1:
case MESA_FORMAT_RGB_DXT1:
/*
* DXTn pitches are Width/4 * blocksize in bytes
* for DXT1: blocksize=8 so Width/4*8 = Width * 2
* for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
*/
t->intel.texelBytes = 2;
textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
break;
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
case MESA_FORMAT_RGBA_DXT3:
t->intel.texelBytes = 4;
textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
break;
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
case MESA_FORMAT_RGBA_DXT5:
t->intel.texelBytes = 4;
textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
break;
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
default:
fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__,
mesa_format);
abort();
return 0;
}
/* Compute which mipmap levels we really want to send to the hardware.
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
* Yes, this looks overly complicated, but it's all needed.
*/
driCalculateTextureFirstLastLevel( (driTextureObject *) t );
/* Figure out the amount of memory required to hold all the mipmap
* levels. Choose the smallest pitch to accomodate the largest
* mipmap:
*/
firstLevel = t->intel.base.firstLevel;
lastLevel = t->intel.base.lastLevel;
numLevels = lastLevel - firstLevel + 1;
/* All images must be loaded at this pitch. Count the number of
* lines required:
*/
switch (tObj->Target) {
case GL_TEXTURE_CUBE_MAP: {
const GLuint dim = tObj->Image[0][firstLevel]->Width;
GLuint face;
pitch = dim * t->intel.texelBytes;
pitch *= 2; /* double pitch for cube layouts */
pitch = (pitch + 3) & ~3;
total_height = dim * 4;
for ( face = 0 ; face < 6 ; face++) {
GLuint x = initial_offsets[face][0] * dim;
GLuint y = initial_offsets[face][1] * dim;
GLuint d = dim;
t->intel.base.dirty_images[face] = ~0;
assert(tObj->Image[face][firstLevel]->Width == dim);
assert(tObj->Image[face][firstLevel]->Height == dim);
for (i = 0; i < numLevels; i++) {
t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
if (!t->intel.image[face][i].image) {
fprintf(stderr, "no image %d %d\n", face, i);
break; /* can't happen */
}
t->intel.image[face][i].offset =
y * pitch + x * t->intel.texelBytes;
t->intel.image[face][i].internalFormat = baseImage->_BaseFormat;
d >>= 1;
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
}
}
break;
}
default:
pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
pitch = (pitch + 3) & ~3;
t->intel.base.dirty_images[0] = ~0;
for ( total_height = i = 0 ; i < numLevels ; i++ ) {
t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
if (!t->intel.image[0][i].image)
break;
t->intel.image[0][i].offset = total_height * pitch;
t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
if (t->intel.image[0][i].image->IsCompressed)
{
if (t->intel.image[0][i].image->Height > 4)
total_height += t->intel.image[0][i].image->Height/4;
else
total_height += 1;
}
else
total_height += MAX2(2, t->intel.image[0][i].image->Height);
}
break;
}
t->intel.Pitch = pitch;
t->intel.base.totalSize = total_height*pitch;
t->intel.max_level = i-1;
t->Setup[I830_TEXREG_TM0S1] =
(((tObj->Image[0][firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) |
((tObj->Image[0][firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) |
textureFormat);
t->Setup[I830_TEXREG_TM0S2] =
(((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) |
TM0S2_CUBE_FACE_ENA_MASK;
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
t->intel.dirty = I830_UPLOAD_TEX_ALL;
return intelUploadTexImages( &i830->intel, &t->intel, 0 );
}
static void i830_import_tex_unit( i830ContextPtr i830,
i830TextureObjectPtr t,
GLuint unit )
{
if(INTEL_DEBUG&DEBUG_TEXTURE)
fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
if (i830->intel.CurrentTexObj[unit])
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
t->intel.base.bound |= (1 << unit);
I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
i830->state.Tex[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
(LOAD_TEXTURE_MAP0 << unit) | 4);
i830->state.Tex[unit][I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE |
t->intel.TextureOffset);
i830->state.Tex[unit][I830_TEXREG_TM0S1] = t->Setup[I830_TEXREG_TM0S1];
i830->state.Tex[unit][I830_TEXREG_TM0S2] = t->Setup[I830_TEXREG_TM0S2];
i830->state.Tex[unit][I830_TEXREG_TM0S3] &= TM0S3_LOD_BIAS_MASK;
i830->state.Tex[unit][I830_TEXREG_TM0S3] |= (t->Setup[I830_TEXREG_TM0S3] &
~TM0S3_LOD_BIAS_MASK);
i830->state.Tex[unit][I830_TEXREG_TM0S4] = t->Setup[I830_TEXREG_TM0S4];
i830->state.Tex[unit][I830_TEXREG_MCS] = (t->Setup[I830_TEXREG_MCS] &
~MAP_UNIT_MASK);
i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE];
i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit);
t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
}
static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
/* The i915 (and related graphics cores) do not support GL_CLAMP. The
* Intel drivers for "other operating systems" implement GL_CLAMP as
* GL_CLAMP_TO_EDGE, so the same is done here.
*/
static GLuint translate_wrap_mode( GLenum wrap )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
switch( wrap ) {
case GL_REPEAT:
return TEXCOORDMODE_WRAP;
case GL_CLAMP:
case GL_CLAMP_TO_EDGE:
return TEXCOORDMODE_CLAMP; /* not really correct */
case GL_CLAMP_TO_BORDER:
return TEXCOORDMODE_CLAMP_BORDER;
case GL_MIRRORED_REPEAT:
return TEXCOORDMODE_MIRROR;
default:
return TEXCOORDMODE_WRAP;
}
}
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
/* Fallback if there's a texture border */
if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
fprintf(stderr, "Texture border\n");
return GL_FALSE;
/* Recalculate all state from scratch. Perhaps not the most
* efficient, but this has gotten complex enough that we need
* something which is understandable and reliable.
*/
static GLboolean i830_update_tex_unit( struct intel_context *intel,
GLuint unit,
GLuint ss3 )
{
GLcontext *ctx = &intel->ctx;
struct i830_context *i830 = i830_context(ctx);
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
struct gl_texture_image *firstImage;
GLuint *state = i830->state.Tex[unit];
memset(state, 0, sizeof(state));
if (!intel_finalize_mipmap_tree(intel, unit))
return GL_FALSE;
/* Get first image here, since intelObj->firstLevel will get set in
* the intel_finalize_mipmap_tree() call above.
*/
firstImage = tObj->Image[0][intelObj->firstLevel];
i830->state.tex_buffer[unit] = intelObj->mt->region->buffer;
i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0,
intelObj->firstLevel);
state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
(LOAD_TEXTURE_MAP0 << unit) | 4);
/* state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */
/* t->intel.TextureOffset); */
state[I830_TEXREG_TM0S1] =
(((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) |
translate_texture_format( firstImage->TexFormat->MesaFormat));
state[I830_TEXREG_TM0S2] =
(((((intelObj->mt->pitch * intelObj->mt->cpp) / 4) - 1) << TM0S2_PITCH_SHIFT) |
TM0S2_CUBE_FACE_ENA_MASK);
{
if (tObj->Target == GL_TEXTURE_CUBE_MAP)
state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
CUBE_NEGX_ENABLE |
CUBE_POSX_ENABLE |
CUBE_NEGY_ENABLE |
CUBE_POSY_ENABLE |
CUBE_NEGZ_ENABLE |
CUBE_POSZ_ENABLE);
else
state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
}
/* Upload teximages (not pipelined)
*/
if (t->intel.base.dirty_images[0]) {
if (!i830SetTexImages( i830, tObj )) {
{
GLuint minFilt, mipFilt, magFilt;
switch (tObj->MinFilter) {
case GL_NEAREST:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_NONE;
break;
case GL_LINEAR:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_NONE;
break;
case GL_NEAREST_MIPMAP_NEAREST:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_NEAREST;
break;
case GL_LINEAR_MIPMAP_NEAREST:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_LINEAR;
break;
case GL_LINEAR_MIPMAP_LINEAR:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_LINEAR;
break;
default:
return GL_FALSE;
}
if ( tObj->MaxAnisotropy > 1.0 ) {
minFilt = FILTER_ANISOTROPIC;
magFilt = FILTER_ANISOTROPIC;
}
else {
switch (tObj->MagFilter) {
case GL_NEAREST:
magFilt = FILTER_NEAREST;
break;
case GL_LINEAR:
magFilt = FILTER_LINEAR;
break;
default:
return GL_FALSE;
}
}
state[I830_TEXREG_TM0S3] = i830->lodbias_tm0s3[unit];
#if 0
/* YUV conversion:
*/
if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
#endif
state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel -
intelObj->firstLevel)*4) << TM0S3_MIN_MIP_SHIFT;
state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
(mipFilt << TM0S3_MIP_FILTER_SHIFT) |
(magFilt << TM0S3_MAG_FILTER_SHIFT));
}
/* Update state if this is a different texture object to last
* time.
*/
if (i830->intel.CurrentTexObj[unit] != &t->intel ||
(t->intel.dirty & I830_UPLOAD_TEX(unit))) {
i830_import_tex_unit( i830, t, unit);
{
GLenum ws = tObj->WrapS;
GLenum wt = tObj->WrapT;
/* 3D textures not available on i830
*/
if (tObj->Target == GL_TEXTURE_3D)
return GL_FALSE;
state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
MAP_UNIT(unit) |
ENABLE_TEXCOORD_PARAMS |
ss3 |
ENABLE_ADDR_V_CNTL |
TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt)) |
ENABLE_ADDR_U_CNTL |
TEXCOORD_ADDR_U_MODE(translate_wrap_mode(ws)));
}
state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0],
tObj->_BorderChan[1],
tObj->_BorderChan[2],
tObj->_BorderChan[3]);
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
return GL_TRUE;
}
static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
mcs &= ~TEXCOORDS_ARE_NORMAL;
mcs |= TEXCOORDS_ARE_IN_TEXELUNITS;
if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
|| (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
i830->state.Tex[unit][I830_TEXREG_CUBE] = 0;
}
return GL_TRUE;
}
static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
mcs |= TEXCOORDS_ARE_NORMAL;
if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
|| (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
i830->state.Tex[unit][I830_TEXREG_CUBE] = 0;
}
return GL_TRUE;
}
static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
const GLuint cube = CUBE_NEGX_ENABLE | CUBE_POSX_ENABLE
| CUBE_NEGY_ENABLE | CUBE_POSY_ENABLE
| CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE;
GLuint face;
mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
mcs |= TEXCOORDS_ARE_NORMAL;
if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
|| (cube != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
i830->state.Tex[unit][I830_TEXREG_CUBE] = cube;
}
/* Upload teximages (not pipelined)
/* memcmp was already disabled, but definitely won't work as the
* region might now change and that wouldn't be detected:
*/
if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
i830SetTexImages( i830, tObj );
}
I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
return GL_TRUE;
}
/* upload (per face) */
for (face = 0; face < 6; face++) {
if (t->intel.base.dirty_images[face]) {
if (!intelUploadTexImages( &i830->intel, &t->intel, face )) {
return GL_FALSE;
}
void i830UpdateTextureState( struct intel_context *intel )
{
struct i830_context *i830 = i830_context(&intel->ctx);
GLboolean ok = GL_TRUE;
GLuint i;
for (i = 0 ; i < I830_TEX_UNITS && ok ; i++) {
switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
case TEXTURE_1D_BIT:
case TEXTURE_2D_BIT:
case TEXTURE_CUBE_BIT:
ok = i830_update_tex_unit( intel, i, TEXCOORDS_ARE_NORMAL );
break;
case TEXTURE_RECT_BIT:
ok = i830_update_tex_unit( intel, i, TEXCOORDS_ARE_IN_TEXELUNITS );
break;
case 0:
if (i830->state.active & I830_UPLOAD_TEX(i))
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE);
break;
case TEXTURE_3D_BIT:
default:
ok = GL_FALSE;
break;
}
}
return GL_TRUE;
}
static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
/* This is happening too often. I need to conditionally send diffuse
* state to the card. Perhaps a diffuse dirty flag of some kind.
* Will need to change this logic if more than 2 texture units are
* used. We need to only do this up to the last unit enabled, or unit
* one if nothing is enabled.
*/
if ( i830->intel.CurrentTexObj[unit] != NULL ) {
/* The old texture is no longer bound to this texture unit.
* Mark it as such.
*/
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
i830->intel.CurrentTexObj[unit] = NULL;
}
return GL_TRUE;
}
static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
if (texUnit->_ReallyEnabled &&
INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024)
return GL_FALSE;
switch(texUnit->_ReallyEnabled) {
case TEXTURE_1D_BIT:
case TEXTURE_2D_BIT:
return (enable_tex_common( ctx, unit ) &&
enable_tex_2d( ctx, unit ));
case TEXTURE_RECT_BIT:
return (enable_tex_common( ctx, unit ) &&
enable_tex_rect( ctx, unit ));
case TEXTURE_CUBE_BIT:
return (enable_tex_common( ctx, unit ) &&
enable_tex_cube( ctx, unit ));
case 0:
return disable_tex( ctx, unit );
default:
return GL_FALSE;
}
}
void i830UpdateTextureState( intelContextPtr intel )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
GLcontext *ctx = &intel->ctx;
GLboolean ok;
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX_ALL, GL_FALSE);
ok = (i830UpdateTexUnit( ctx, 0 ) &&
i830UpdateTexUnit( ctx, 1 ) &&
i830UpdateTexUnit( ctx, 2 ) &&
i830UpdateTexUnit( ctx, 3 ));
FALLBACK( intel, I830_FALLBACK_TEXTURE, !ok );
if (ok)
@@ -481,3 +314,8 @@ void i830UpdateTextureState( intelContextPtr intel )

View File

@@ -30,11 +30,12 @@
#include "i830_reg.h"
#include "intel_batchbuffer.h"
#include "intel_regions.h"
#include "tnl/t_context.h"
#include "tnl/t_vertex.h"
static GLboolean i830_check_vertex_size( intelContextPtr intel,
static GLboolean i830_check_vertex_size( struct intel_context *intel,
GLuint expected );
#define SZ_TO_HW(sz) ((sz-2)&0x3)
@@ -59,10 +60,10 @@ do { \
#define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
#define TEXBIND_SET(n, x) ((x)<<((n)*4))
static void i830_render_start( intelContextPtr intel )
static void i830_render_start( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
i830ContextPtr i830 = I830_CONTEXT(intel);
struct i830_context *i830 = i830_context(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint index = tnl->render_inputs;
@@ -163,6 +164,7 @@ static void i830_render_start( intelContextPtr intel )
v2 != i830->state.Ctx[I830_CTXREG_VF2] ||
mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] ||
index != i830->last_index) {
int k;
I830_STATECHANGE( i830, I830_UPLOAD_CTX );
@@ -182,14 +184,15 @@ static void i830_render_start( intelContextPtr intel )
i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1;
i830->last_index = index;
assert(i830_check_vertex_size( intel, intel->vertex_size ));
k = i830_check_vertex_size( intel, intel->vertex_size );
assert(k);
}
}
static void i830_reduced_primitive_state( intelContextPtr intel,
static void i830_reduced_primitive_state( struct intel_context *intel,
GLenum rprim )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
struct i830_context *i830 = i830_context(&intel->ctx);
GLuint st1 = i830->state.Stipple[I830_STPREG_ST1];
st1 &= ~ST1_ENABLE;
@@ -217,10 +220,10 @@ static void i830_reduced_primitive_state( intelContextPtr intel,
/* Pull apart the vertex format registers and figure out how large a
* vertex is supposed to be.
*/
static GLboolean i830_check_vertex_size( intelContextPtr intel,
static GLboolean i830_check_vertex_size( struct intel_context *intel,
GLuint expected )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
struct i830_context *i830 = i830_context(&intel->ctx);
int vft0 = i830->current->Ctx[I830_CTXREG_VF];
int vft1 = i830->current->Ctx[I830_CTXREG_VF2];
int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT;
@@ -257,16 +260,11 @@ static GLboolean i830_check_vertex_size( intelContextPtr intel,
return sz == expected;
}
static void i830_emit_invarient_state( intelContextPtr intel )
static void i830_emit_invarient_state( struct intel_context *intel )
{
BATCH_LOCALS;
BEGIN_BATCH( 200 );
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3));
BEGIN_BATCH(200, 0);
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
OUT_BATCH(0);
@@ -330,13 +328,6 @@ static void i830_emit_invarient_state( intelContextPtr intel )
TRI_FAN_PROVOKE_VRTX(2) |
TRI_STRIP_PROVOKE_VRTX(2));
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |
DISABLE_SCISSOR_RECT);
OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
OUT_BATCH(0);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
@@ -355,18 +346,20 @@ static void i830_emit_invarient_state( intelContextPtr intel )
#define emit( intel, state, size ) \
do { \
int k; \
BEGIN_BATCH( size / sizeof(GLuint)); \
for (k = 0 ; k < size / sizeof(GLuint) ; k++) \
BEGIN_BATCH(size / sizeof(GLuint), 0); \
for (k = 0 ; k < size / sizeof(GLuint) ; k++) { \
if (0) _mesa_printf(" 0x%08x\n", state[k]); \
OUT_BATCH(state[k]); \
} \
ADVANCE_BATCH(); \
} while (0);
} while (0)
/* Push the state into the sarea and/or texture memory.
*/
static void i830_emit_state( intelContextPtr intel )
static void i830_emit_state( struct intel_context *intel )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
struct i830_context *i830 = i830_context(&intel->ctx);
struct i830_hw_state *state = i830->current;
int i;
GLuint dirty;
@@ -374,29 +367,79 @@ static void i830_emit_state( intelContextPtr intel )
dirty = state->active & ~state->emitted;
if (dirty & I830_UPLOAD_INVARIENT) {
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "I830_UPLOAD_INVARIENT:\n");
i830_emit_invarient_state( intel );
}
if (dirty & I830_UPLOAD_CTX) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n");
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "I830_UPLOAD_CTX:\n");
emit( i830, state->Ctx, sizeof(state->Ctx) );
}
if (dirty & I830_UPLOAD_BUFFERS) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");
emit( i830, state->Buffer, sizeof(state->Buffer) );
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");
BEGIN_BATCH(I830_DEST_SETUP_SIZE+2, 0);
OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR0]);
OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]);
OUT_RELOC(state->draw_region->buffer, DRM_MM_TT|DRM_MM_WRITE, 0);
if (state->depth_region) {
OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR0]);
OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]);
OUT_RELOC(state->depth_region->buffer, DRM_MM_TT |DRM_MM_WRITE, 0);
}
OUT_BATCH(state->Buffer[I830_DESTREG_DV0]);
OUT_BATCH(state->Buffer[I830_DESTREG_DV1]);
OUT_BATCH(state->Buffer[I830_DESTREG_SENABLE]);
OUT_BATCH(state->Buffer[I830_DESTREG_SR0]);
OUT_BATCH(state->Buffer[I830_DESTREG_SR1]);
OUT_BATCH(state->Buffer[I830_DESTREG_SR2]);
ADVANCE_BATCH();
}
if (dirty & I830_UPLOAD_STIPPLE) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");
emit( i830, state->Stipple, sizeof(state->Stipple) );
}
for (i = 0; i < I830_TEX_UNITS; i++) {
if ((dirty & I830_UPLOAD_TEX(i))) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);
emit( i830, state->Tex[i], sizeof(state->Tex[i]));
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);
BEGIN_BATCH(I830_TEX_SETUP_SIZE+1, 0);
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0LI]);
if (state->tex_buffer[i]) {
OUT_RELOC(state->tex_buffer[i],
DRM_MM_TT|DRM_MM_READ,
state->tex_offset[i] | TM0S0_USE_FENCE);
}
else {
assert(i == 0);
assert(state == &i830->meta);
OUT_BATCH(0);
}
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S1]);
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S2]);
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S3]);
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S4]);
OUT_BATCH(state->Tex[i][I830_TEXREG_MCS]);
OUT_BATCH(state->Tex[i][I830_TEXREG_CUBE]);
}
if (dirty & I830_UPLOAD_TEXBLEND(i)) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d):\n", i);
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d): %d words\n", i,
state->TexBlendWordsUsed[i]);
emit( i830, state->TexBlend[i],
state->TexBlendWordsUsed[i] * 4 );
}
@@ -405,52 +448,54 @@ static void i830_emit_state( intelContextPtr intel )
state->emitted |= dirty;
}
static void i830_destroy_context( intelContextPtr intel )
static void i830_destroy_context( struct intel_context *intel )
{
_tnl_free_vertices(&intel->ctx);
}
static void i830_set_draw_offset( intelContextPtr intel, int offset )
static void i830_set_draw_region( struct intel_context *intel,
struct intel_region *draw_region,
struct intel_region *depth_region)
{
i830ContextPtr i830 = I830_CONTEXT(intel);
struct i830_context *i830 = i830_context(&intel->ctx);
intel_region_release(intel, &i830->state.draw_region);
intel_region_release(intel, &i830->state.depth_region);
intel_region_reference(&i830->state.draw_region, draw_region);
intel_region_reference(&i830->state.depth_region, depth_region);
/* XXX FBO: Need code from i915_set_draw_region() */
I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS );
i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset;
}
/* This isn't really handled at the moment.
*/
static void i830_lost_hardware( intelContextPtr intel )
static void i830_lost_hardware( struct intel_context *intel )
{
I830_CONTEXT(intel)->state.emitted = 0;
struct i830_context *i830 = i830_context(&intel->ctx);
i830->state.emitted = 0;
}
static void i830_emit_flush( intelContextPtr intel )
static GLuint i830_flush_cmd( void )
{
BATCH_LOCALS;
BEGIN_BATCH(2);
OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE );
OUT_BATCH( 0 );
ADVANCE_BATCH();
return MI_FLUSH | FLUSH_MAP_CACHE;
}
void i830InitVtbl( i830ContextPtr i830 )
void i830InitVtbl( struct i830_context *i830 )
{
i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj;
i830->intel.vtbl.check_vertex_size = i830_check_vertex_size;
i830->intel.vtbl.clear_with_tris = i830ClearWithTris;
i830->intel.vtbl.destroy = i830_destroy_context;
i830->intel.vtbl.emit_invarient_state = i830_emit_invarient_state;
i830->intel.vtbl.emit_state = i830_emit_state;
i830->intel.vtbl.lost_hardware = i830_lost_hardware;
i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state;
i830->intel.vtbl.set_draw_offset = i830_set_draw_offset;
i830->intel.vtbl.set_draw_region = i830_set_draw_region;
i830->intel.vtbl.update_texture_state = i830UpdateTextureState;
i830->intel.vtbl.emit_flush = i830_emit_flush;
i830->intel.vtbl.flush_cmd = i830_flush_cmd;
i830->intel.vtbl.render_start = i830_render_start;
}

View File

@@ -41,6 +41,10 @@
#include "utils.h"
#include "i915_reg.h"
#include "intel_bufmgr.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
/***************************************
* Mesa's Driver Functions
***************************************/
@@ -65,7 +69,7 @@ static void i915InvalidateState( GLcontext *ctx, GLuint new_state )
_ac_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
_tnl_invalidate_vertex_state( ctx, new_state );
INTEL_CONTEXT(ctx)->NewGLState |= new_state;
intel_context(ctx)->NewGLState |= new_state;
/* Todo: gather state values under which tracked parameters become
* invalidated, add callbacks for things like
@@ -99,13 +103,16 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
void *sharedContextPrivate)
{
struct dd_function_table functions;
i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context);
intelContextPtr intel = &i915->intel;
struct i915_context *i915 = (struct i915_context *) CALLOC_STRUCT(i915_context);
struct intel_context *intel = &i915->intel;
GLcontext *ctx = &intel->ctx;
if (!i915) return GL_FALSE;
_mesa_printf( "\ntexmem branch (i915, drop3)\n\n");
i915InitVtbl( i915 );
i915InitMetaFuncs( i915 );
i915InitDriverFunctions( &functions );
@@ -119,48 +126,28 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS;
ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS;
intel->nr_heaps = 1;
intel->texture_heaps[0] =
driCreateTextureHeap( 0, intel,
intel->intelScreen->tex.size,
12,
I830_NR_TEX_REGIONS,
intel->sarea->texList,
& intel->sarea->texAge,
& intel->swapped,
sizeof( struct i915_texture_object ),
(destroy_texture_object_t *)intelDestroyTexObj );
/* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are
* tightly packed, but they're not in Intel graphics
* hardware.
/* Advertise the full hardware capabilities. The new memory
* manager should cope much better with overload situations:
*/
ctx->Const.MaxTextureUnits = 1;
driCalculateMaxTextureLevels( intel->texture_heaps,
intel->nr_heaps,
&intel->ctx.Const,
4,
11, /* max 2D texture size is 2048x2048 */
8, /* 3D texture */
11, /* cube texture. */
11, /* rect texture */
12,
GL_FALSE );
ctx->Const.MaxTextureLevels = 12;
ctx->Const.Max3DTextureLevels = 9;
ctx->Const.MaxCubeTextureLevels = 12;
ctx->Const.MaxTextureRectSize = (1<<11);
ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
/* GL_ARB_fragment_program limits - don't think Mesa actually
* validates programs against these, and in any case one ARB
* instruction can translate to more than one HW instruction, so
* we'll still have to check and fallback each time.
*/
*/
ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY;
ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */
ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT;
ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN;
ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN;
ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN +
I915_MAX_TEX_INSN);
I915_MAX_TEX_INSN);
ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT;
ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */

View File

@@ -43,6 +43,8 @@
#define I915_UPLOAD_PROGRAM 0x8
#define I915_UPLOAD_CONSTANTS 0x10
#define I915_UPLOAD_FOG 0x20
#define I915_UPLOAD_INVARIENT 0x40
#define I915_UPLOAD_DEFAULTS 0x80
#define I915_UPLOAD_TEX(i) (0x00010000<<(i))
#define I915_UPLOAD_TEX_ALL (0x00ff0000)
#define I915_UPLOAD_TEX_0_SHIFT 16
@@ -52,10 +54,8 @@
*/
#define I915_DESTREG_CBUFADDR0 0
#define I915_DESTREG_CBUFADDR1 1
#define I915_DESTREG_CBUFADDR2 2
#define I915_DESTREG_DBUFADDR0 3
#define I915_DESTREG_DBUFADDR1 4
#define I915_DESTREG_DBUFADDR2 5
#define I915_DESTREG_DV0 6
#define I915_DESTREG_DV1 7
#define I915_DESTREG_SENABLE 8
@@ -86,7 +86,6 @@
#define I915_STPREG_ST1 1
#define I915_STP_SETUP_SIZE 2
#define I915_TEXREG_MS2 0
#define I915_TEXREG_MS3 1
#define I915_TEXREG_MS4 2
#define I915_TEXREG_SS2 3
@@ -94,6 +93,15 @@
#define I915_TEXREG_SS4 5
#define I915_TEX_SETUP_SIZE 6
#define I915_DEFREG_C0 0
#define I915_DEFREG_C1 1
#define I915_DEFREG_S0 2
#define I915_DEFREG_S1 3
#define I915_DEFREG_Z0 4
#define I915_DEFREG_Z1 5
#define I915_DEF_SETUP_SIZE 6
#define I915_MAX_CONSTANT 32
#define I915_CONSTANT_SIZE (2+(4*I915_MAX_CONSTANT))
@@ -163,8 +171,6 @@ struct i915_fragment_program {
GLuint nr_params;
/* Helpers for i915_texprog.c:
*/
GLuint src_texture; /* Reg containing sampled texture color,
@@ -185,13 +191,6 @@ struct i915_fragment_program {
struct i915_texture_object
{
struct intel_texture_object intel;
GLenum lastTarget;
GLboolean refs_border_color;
GLuint Setup[I915_TEX_SETUP_SIZE];
};
#define I915_TEX_UNITS 8
@@ -201,11 +200,27 @@ struct i915_hw_state {
GLuint Buffer[I915_DEST_SETUP_SIZE];
GLuint Stipple[I915_STP_SETUP_SIZE];
GLuint Fog[I915_FOG_SETUP_SIZE];
GLuint Defaults[I915_DEF_SETUP_SIZE];
GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE];
GLuint Constant[I915_CONSTANT_SIZE];
GLuint ConstantSize;
GLuint Program[I915_PROGRAM_SIZE];
GLuint ProgramSize;
/* Region pointers for relocation:
*/
struct intel_region *draw_region;
struct intel_region *depth_region;
/* struct intel_region *tex_region[I915_TEX_UNITS]; */
/* Regions aren't actually that appropriate here as the memory may
* be from a PBO or FBO. Just use the buffer id. Will have to do
* this for draw and depth for FBO's...
*/
GLuint tex_buffer[I915_TEX_UNITS];
GLuint tex_offset[I915_TEX_UNITS];
GLuint active; /* I915_UPLOAD_* */
GLuint emitted; /* I915_UPLOAD_* */
};
@@ -220,6 +235,8 @@ struct i915_context
GLuint last_ReallyEnabled;
GLuint vertex_fog;
GLuint lodbias_ss2[MAX_TEXTURE_UNITS];
struct i915_fragment_program tex_program;
struct i915_fragment_program *current_program;
@@ -228,24 +245,14 @@ struct i915_context
};
typedef struct i915_context *i915ContextPtr;
typedef struct i915_texture_object *i915TextureObjectPtr;
#define I915_CONTEXT(ctx) ((i915ContextPtr)(ctx))
#define I915_STATECHANGE(i915, flag) \
do { \
if (0) fprintf(stderr, "I915_STATECHANGE %x in %s\n", flag, __FUNCTION__); \
INTEL_FIREVERTICES( &(i915)->intel ); \
(i915)->state.emitted &= ~(flag); \
} while (0)
#define I915_ACTIVESTATE(i915, flag, mode) \
do { \
if (0) fprintf(stderr, "I915_ACTIVESTATE %x %d in %s\n", \
flag, mode, __FUNCTION__); \
INTEL_FIREVERTICES( &(i915)->intel ); \
if (mode) \
(i915)->state.active |= (flag); \
@@ -257,7 +264,13 @@ do { \
/*======================================================================
* i915_vtbl.c
*/
extern void i915InitVtbl( i915ContextPtr i915 );
extern void i915InitVtbl( struct i915_context *i915 );
extern void
i915_state_draw_region(struct intel_context *intel,
struct i915_hw_state *state,
struct intel_region *color_region,
struct intel_region *depth_region);
@@ -294,7 +307,7 @@ extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
/*======================================================================
* i915_texprog.c
*/
extern void i915ValidateTextureProgram( i915ContextPtr i915 );
extern void i915ValidateTextureProgram( struct i915_context *i915 );
/*======================================================================
@@ -308,44 +321,43 @@ extern void i915_print_ureg( const char *msg, GLuint ureg );
* i915_state.c
*/
extern void i915InitStateFunctions( struct dd_function_table *functions );
extern void i915InitState( i915ContextPtr i915 );
extern void i915InitState( struct i915_context *i915 );
extern void i915_update_fog( GLcontext *ctx );
/*======================================================================
* i915_tex.c
*/
extern void i915UpdateTextureState( intelContextPtr intel );
extern void i915UpdateTextureState( struct intel_context *intel );
extern void i915InitTextureFuncs( struct dd_function_table *functions );
extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj );
/*======================================================================
* i915_metaops.c
*/
extern GLboolean
i915TryTextureReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels );
extern GLboolean
i915TryTextureDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
extern void
i915ClearWithTris( intelContextPtr intel, GLbitfield mask,
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
void i915InitMetaFuncs( struct i915_context *i915 );
/*======================================================================
* i915_fragprog.c
*/
extern void i915ValidateFragmentProgram( i915ContextPtr i915 );
extern void i915ValidateFragmentProgram( struct i915_context *i915 );
extern void i915InitFragProgFuncs( struct dd_function_table *functions );
/*======================================================================
* Inline conversion functions. These are better-typed than the
* macros used previously:
*/
static INLINE struct i915_context *
i915_context( GLcontext *ctx )
{
return (struct i915_context *)ctx;
}
#define I915_CONTEXT(ctx) i915_context(ctx)
#endif

View File

@@ -806,7 +806,7 @@ static void check_wpos( struct i915_fragment_program *p )
static void translate_program( struct i915_fragment_program *p )
{
i915ContextPtr i915 = I915_CONTEXT(p->ctx);
struct i915_context *i915 = I915_CONTEXT(p->ctx);
i915_init_program( i915, p );
check_wpos( p );
@@ -840,7 +840,7 @@ static void i915BindProgram( GLcontext *ctx,
struct program *prog )
{
if (target == GL_FRAGMENT_PROGRAM_ARB) {
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
struct i915_fragment_program *p = (struct i915_fragment_program *)prog;
if (i915->current_program == p)
@@ -896,7 +896,7 @@ static void i915DeleteProgram( GLcontext *ctx,
struct program *prog )
{
if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
struct i915_fragment_program *p = (struct i915_fragment_program *)prog;
if (i915->current_program == p)
@@ -940,10 +940,10 @@ static void i915ProgramStringNotify( GLcontext *ctx,
}
void i915ValidateFragmentProgram( i915ContextPtr i915 )
void i915ValidateFragmentProgram( struct i915_context *i915 )
{
GLcontext *ctx = &i915->intel.ctx;
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
@@ -1028,6 +1028,7 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 )
if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
int k;
I915_STATECHANGE( i915, I915_UPLOAD_CTX );
@@ -1044,7 +1045,8 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 )
i915->state.Ctx[I915_CTXREG_LIS2] = s2;
i915->state.Ctx[I915_CTXREG_LIS4] = s4;
assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size ));
k = intel->vtbl.check_vertex_size( intel, intel->vertex_size );
assert(k);
}
if (!p->params_uptodate)

View File

@@ -34,44 +34,45 @@
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_ioctl.h"
#include "intel_regions.h"
#include "i915_context.h"
#include "i915_reg.h"
/* A large amount of state doesn't need to be uploaded.
/* We touch almost everything:
*/
#define ACTIVE (I915_UPLOAD_PROGRAM | \
I915_UPLOAD_STIPPLE | \
#define ACTIVE (I915_UPLOAD_INVARIENT | \
I915_UPLOAD_CTX | \
I915_UPLOAD_BUFFERS | \
I915_UPLOAD_STIPPLE | \
I915_UPLOAD_PROGRAM | \
I915_UPLOAD_FOG | \
I915_UPLOAD_TEX(0))
#define SET_STATE( i915, STATE ) \
#define SET_STATE( i915, STATE ) \
do { \
i915->current->emitted &= ~ACTIVE; \
i915->current = &i915->STATE; \
i915->current = &i915->STATE; \
i915->current->emitted &= ~ACTIVE; \
} while (0)
/* Operations where the 3D engine is decoupled temporarily from the
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void set_initial_state( i915ContextPtr i915 )
{
memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
i915->meta.active = ACTIVE;
i915->meta.emitted = 0;
}
static void set_no_depth_stencil_write( i915ContextPtr i915 )
static void meta_no_stencil_write( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
*/
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE);
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
static void meta_no_depth_write( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
*/
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
@@ -80,12 +81,33 @@ static void set_no_depth_stencil_write( i915ContextPtr i915 )
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
static void meta_depth_replace( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_TRUE )
* ctx->Driver.DepthMask( ctx, GL_TRUE )
*/
i915->meta.Ctx[I915_CTXREG_LIS6] |= (S6_DEPTH_TEST_ENABLE |
S6_DEPTH_WRITE_ENABLE);
/* ctx->Driver.DepthFunc( ctx, GL_REPLACE )
*/
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK;
i915->meta.Ctx[I915_CTXREG_LIS6] |=
COMPAREFUNC_ALWAYS << S6_DEPTH_TEST_FUNC_SHIFT;
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
/* Set stencil unit to replace always with the reference value.
*/
static void set_stencil_replace( i915ContextPtr i915,
static void meta_stencil_replace( struct intel_context *intel,
GLuint s_mask,
GLuint s_clear)
{
struct i915_context *i915 = i915_context(&intel->ctx);
GLuint op = STENCILOP_REPLACE;
GLuint func = COMPAREFUNC_ALWAYS;
@@ -94,13 +116,6 @@ static void set_stencil_replace( i915ContextPtr i915,
i915->meta.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE);
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
*/
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
S6_DEPTH_WRITE_ENABLE);
/* ctx->Driver.StencilMask( ctx, s_mask )
*/
i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
@@ -108,7 +123,6 @@ static void set_stencil_replace( i915ContextPtr i915,
i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
STENCIL_WRITE_MASK(s_mask));
/* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
*/
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
@@ -137,8 +151,9 @@ static void set_stencil_replace( i915ContextPtr i915,
}
static void set_color_mask( i915ContextPtr i915, GLboolean state )
static void meta_color_mask( struct intel_context *intel, GLboolean state )
{
struct i915_context *i915 = i915_context(&intel->ctx);
const GLuint mask = (S5_WRITEDISABLE_RED |
S5_WRITEDISABLE_GREEN |
S5_WRITEDISABLE_BLUE |
@@ -159,6 +174,28 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state )
static void meta_import_pixel_state( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
memcpy(i915->meta.Fog, i915->state.Fog, I915_FOG_SETUP_SIZE * 4);
i915->meta.Ctx[I915_CTXREG_LIS5] = i915->state.Ctx[I915_CTXREG_LIS5];
i915->meta.Ctx[I915_CTXREG_LIS6] = i915->state.Ctx[I915_CTXREG_LIS6];
i915->meta.Ctx[I915_CTXREG_STATE4] = i915->state.Ctx[I915_CTXREG_STATE4];
i915->meta.Ctx[I915_CTXREG_BLENDCOLOR1] = i915->state.Ctx[I915_CTXREG_BLENDCOLOR1];
i915->meta.Ctx[I915_CTXREG_IAB] = i915->state.Ctx[I915_CTXREG_IAB];
i915->meta.Buffer[I915_DESTREG_SENABLE] = i915->state.Buffer[I915_DESTREG_SENABLE];
i915->meta.Buffer[I915_DESTREG_SR1] = i915->state.Buffer[I915_DESTREG_SR1];
i915->meta.Buffer[I915_DESTREG_SR2] = i915->state.Buffer[I915_DESTREG_SR2];
i915->meta.emitted &= ~I915_UPLOAD_FOG;
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
#define REG( type, nr ) (((type)<<5)|(nr))
@@ -210,8 +247,10 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state )
static void set_no_texture( i915ContextPtr i915 )
static void meta_no_texture( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
static const GLuint prog[] = {
_3DSTATE_PIXEL_SHADER_PROGRAM,
@@ -240,9 +279,10 @@ static void set_no_texture( i915ContextPtr i915 )
i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
}
#if 0
static void enable_texture_blend_replace( i915ContextPtr i915 )
static void meta_texture_blend_replace( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
static const GLuint prog[] = {
_3DSTATE_PIXEL_SHADER_PROGRAM,
@@ -285,78 +325,126 @@ static void enable_texture_blend_replace( i915ContextPtr i915 )
/* Set up an arbitary piece of memory as a rectangular texture
* (including the front or back buffer).
*/
static void set_tex_rect_source( i915ContextPtr i915,
GLuint offset,
GLuint width,
GLuint height,
GLuint pitch,
GLuint textureFormat )
static GLboolean meta_tex_rect_source( struct intel_context *intel,
GLuint buffer,
GLuint offset,
GLuint pitch,
GLuint height,
GLenum format,
GLenum type)
{
struct i915_context *i915 = i915_context(&intel->ctx);
GLuint unit = 0;
GLint numLevels = 1;
GLuint *state = i915->meta.Tex[0];
GLuint textureFormat;
GLuint cpp;
pitch *= i915->intel.intelScreen->cpp;
/* A full implementation of this would do the upload through
* glTexImage2d, and get all the conversion operations at that
* point. We are restricted, but still at least have access to the
* fragment program swizzle.
*/
switch (format) {
case GL_BGRA:
switch (type) {
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_BYTE:
textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888);
cpp = 4;
break;
default:
return GL_FALSE;
}
break;
case GL_RGBA:
switch (type) {
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_BYTE:
textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888);
cpp = 4;
break;
default:
return GL_FALSE;
}
break;
case GL_BGR:
switch (type) {
case GL_UNSIGNED_SHORT_5_6_5_REV:
textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
cpp = 2;
break;
default:
return GL_FALSE;
}
break;
case GL_RGB:
switch (type) {
case GL_UNSIGNED_SHORT_5_6_5:
textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
cpp = 2;
break;
default:
return GL_FALSE;
}
break;
/* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
/* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
default:
return GL_FALSE;
}
if ((pitch * cpp) & 3) {
_mesa_printf("%s: texture is not dword pitch\n", __FUNCTION__);
return GL_FALSE;
}
/* intel_region_release(intel, &i915->meta.tex_region[0]); */
/* intel_region_reference(&i915->meta.tex_region[0], region); */
i915->meta.tex_buffer[0] = buffer;
i915->meta.tex_offset[0] = offset;
state[I915_TEXREG_MS2] = offset;
state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) |
((width - 1) << MS3_WIDTH_SHIFT) |
textureFormat |
MS3_USE_FENCE_REGS);
((pitch - 1) << MS3_WIDTH_SHIFT) |
textureFormat |
MS3_USE_FENCE_REGS);
state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
MS4_CUBE_FACE_ENA_MASK |
((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
state[I915_TEXREG_MS4] = (((((pitch * cpp) / 4) - 1) << MS4_PITCH_SHIFT) |
MS4_CUBE_FACE_ENA_MASK |
((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) |
(MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
(FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
(MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
(FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) |
(TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
(TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
(unit<<SS3_TEXTUREMAP_INDEX_SHIFT));
(TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
(TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
(unit<<SS3_TEXTUREMAP_INDEX_SHIFT));
state[I915_TEXREG_SS4] = 0;
i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
return GL_TRUE;
}
#endif
/* Select between front and back draw buffers.
/**
* Set the color and depth drawing region for meta ops.
*/
static void set_draw_offset( i915ContextPtr i915,
GLuint offset )
static void meta_draw_region( struct intel_context *intel,
struct intel_region *color_region,
struct intel_region *depth_region )
{
i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset;
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
struct i915_context *i915 = i915_context(&intel->ctx);
i915_state_draw_region(intel, &i915->meta, color_region, depth_region);
}
#if 0
/* Setup an arbitary draw format, useful for targeting texture or agp
* memory.
*/
static void set_draw_format( i915ContextPtr i915,
GLuint format,
GLuint depth_format)
{
i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
format |
LOD_PRECLAMP_OGL |
TEX_DEFAULT_COLOR_OGL |
depth_format);
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
/* fprintf(stderr, "%s: DV1: %x\n", */
/* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
}
#endif
static void set_vertex_format( i915ContextPtr i915 )
static void set_vertex_format( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
i915->meta.Ctx[I915_CTXREG_LIS2] =
(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
@@ -371,146 +459,52 @@ static void set_vertex_format( i915ContextPtr i915 )
i915->meta.Ctx[I915_CTXREG_LIS4] |=
(S4_VFMT_COLOR |
S4_VFMT_SPEC_FOG |
S4_VFMT_XYZW);
S4_VFMT_XYZ);
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
static void draw_quad(i915ContextPtr i915,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1 )
/* Operations where the 3D engine is decoupled temporarily from the
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void install_meta_state( struct intel_context *intel )
{
GLuint vertex_size = 8;
GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
PRIM3D_TRIFAN,
4 * vertex_size,
vertex_size );
intelVertex tmp;
int i;
struct i915_context *i915 = i915_context(&intel->ctx);
memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
i915->meta.active = ACTIVE;
i915->meta.emitted = 0;
if (0)
fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
__FUNCTION__,
x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1);
/* initial vertex, left bottom */
tmp.v.x = x0;
tmp.v.y = y0;
tmp.v.z = 1.0;
tmp.v.w = 1.0;
tmp.v.color.red = red;
tmp.v.color.green = green;
tmp.v.color.blue = blue;
tmp.v.color.alpha = alpha;
tmp.v.specular.red = 0;
tmp.v.specular.green = 0;
tmp.v.specular.blue = 0;
tmp.v.specular.alpha = 0;
tmp.v.u0 = s0;
tmp.v.v0 = t0;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* right bottom */
vb += vertex_size;
tmp.v.x = x1;
tmp.v.u0 = s1;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* right top */
vb += vertex_size;
tmp.v.y = y1;
tmp.v.v0 = t1;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* left top */
vb += vertex_size;
tmp.v.x = x0;
tmp.v.u0 = s0;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
SET_STATE(i915, meta);
set_vertex_format(intel);
meta_no_texture(intel);
}
void
i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
static void leave_meta_state( struct intel_context *intel )
{
i915ContextPtr i915 = I915_CONTEXT( intel );
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelScreenPrivate *screen = intel->intelScreen;
int x0, y0, x1, y1;
SET_STATE( i915, meta );
set_initial_state( i915 );
set_no_texture( i915 );
set_vertex_format( i915 );
LOCK_HARDWARE(intel);
if(!all) {
x0 = cx;
y0 = cy;
x1 = x0 + cw;
y1 = y0 + ch;
} else {
x0 = 0;
y0 = 0;
x1 = x0 + dPriv->w;
y1 = y0 + dPriv->h;
}
/* Don't do any clipping to screen - these are window coordinates.
* The active cliprects will be applied as for any other geometry.
*/
if (mask & BUFFER_BIT_FRONT_LEFT) {
set_no_depth_stencil_write( i915 );
set_color_mask( i915, GL_TRUE );
set_draw_offset( i915, screen->front.offset );
draw_quad(i915, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if (mask & BUFFER_BIT_BACK_LEFT) {
set_no_depth_stencil_write( i915 );
set_color_mask( i915, GL_TRUE );
set_draw_offset( i915, screen->back.offset );
draw_quad(i915, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if (mask & BUFFER_BIT_STENCIL) {
set_stencil_replace( i915,
intel->ctx.Stencil.WriteMask[0],
intel->ctx.Stencil.Clear);
set_color_mask( i915, GL_FALSE );
set_draw_offset( i915, screen->front.offset ); /* could be either? */
draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
}
UNLOCK_HARDWARE(intel);
SET_STATE( i915, state );
struct i915_context *i915 = i915_context(&intel->ctx);
intel_region_release(intel, &i915->meta.draw_region);
intel_region_release(intel, &i915->meta.depth_region);
/* intel_region_release(intel, &i915->meta.tex_region[0]); */
SET_STATE(i915, state);
}
void i915InitMetaFuncs( struct i915_context *i915 )
{
i915->intel.vtbl.install_meta_state = install_meta_state;
i915->intel.vtbl.leave_meta_state = leave_meta_state;
i915->intel.vtbl.meta_no_depth_write = meta_no_depth_write;
i915->intel.vtbl.meta_no_stencil_write = meta_no_stencil_write;
i915->intel.vtbl.meta_stencil_replace = meta_stencil_replace;
i915->intel.vtbl.meta_depth_replace = meta_depth_replace;
i915->intel.vtbl.meta_color_mask = meta_color_mask;
i915->intel.vtbl.meta_no_texture = meta_no_texture;
i915->intel.vtbl.meta_texture_blend_replace = meta_texture_blend_replace;
i915->intel.vtbl.meta_tex_rect_source = meta_tex_rect_source;
i915->intel.vtbl.meta_draw_region = meta_draw_region;
i915->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state;
}

View File

@@ -144,7 +144,8 @@ GLuint i915_emit_arith( struct i915_fragment_program *p,
GLuint nr_const = 0;
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
assert(dest);
if (GET_UREG_TYPE(src0) == REG_TYPE_CONST) c[nr_const++] = 0;
if (GET_UREG_TYPE(src1) == REG_TYPE_CONST) c[nr_const++] = 1;
@@ -202,7 +203,8 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
GLuint op )
{
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
assert(dest);
if (GET_UREG_TYPE(coord) != REG_TYPE_T) {
p->nr_tex_indirect++;
@@ -358,7 +360,7 @@ void i915_program_error( struct i915_fragment_program *p, const char *msg )
p->error = 1;
}
void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p )
void i915_init_program( struct i915_context *i915, struct i915_fragment_program *p )
{
GLcontext *ctx = &i915->intel.ctx;
TNLcontext *tnl = TNL_CONTEXT( ctx );
@@ -431,7 +433,7 @@ void i915_fini_program( struct i915_fragment_program *p )
p->declarations[0] |= program_size + decl_size - 2;
}
void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p )
void i915_upload_program( struct i915_context *i915, struct i915_fragment_program *p )
{
GLuint program_size = p->csr - p->program;
GLuint decl_size = p->decl - p->declarations;

View File

@@ -84,7 +84,7 @@
/* One neat thing about the UREG representation:
*/
static __inline int swizzle( int reg, int x, int y, int z, int w )
static INLINE int swizzle( int reg, int x, int y, int z, int w )
{
return ((reg & ~UREG_XYZW_CHANNEL_MASK) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, x ), 0 ) |
@@ -95,7 +95,7 @@ static __inline int swizzle( int reg, int x, int y, int z, int w )
/* Another neat thing about the UREG representation:
*/
static __inline int negate( int reg, int x, int y, int z, int w )
static INLINE int negate( int reg, int x, int y, int z, int w )
{
return reg ^ (((x&1)<<UREG_CHANNEL_X_NEGATE_SHIFT)|
((y&1)<<UREG_CHANNEL_Y_NEGATE_SHIFT)|
@@ -149,10 +149,10 @@ extern GLuint i915_emit_param4fv( struct i915_fragment_program *p,
extern void i915_program_error( struct i915_fragment_program *p,
const char *msg );
extern void i915_init_program( i915ContextPtr i915,
extern void i915_init_program( struct i915_context *i915,
struct i915_fragment_program *p );
extern void i915_upload_program( i915ContextPtr i915,
extern void i915_upload_program( struct i915_context *i915,
struct i915_fragment_program *p );
extern void i915_fini_program( struct i915_fragment_program *p );

View File

@@ -435,10 +435,10 @@
#define LOGICOP_MASK (0xf<<18)
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
#define ENABLE_STENCIL_TEST_MASK (1<<17)
#define STENCIL_TEST_MASK(x) ((x)<<8)
#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8)
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
#define ENABLE_STENCIL_WRITE_MASK (1<<16)
#define STENCIL_WRITE_MASK(x) (x)
#define STENCIL_WRITE_MASK(x) ((x)&0xff)
/* _3DSTATE_MODES_5, p220 */
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
@@ -824,10 +824,14 @@
#define ST1_ENABLE (1<<16)
#define ST1_MASK (0xffff)
#define _3DSTATE_DEFAULT_Z ((0x3<<29)|(0x1d<<24)|(0x98<<16))
#define _3DSTATE_DEFAULT_DIFFUSE ((0x3<<29)|(0x1d<<24)|(0x99<<16))
#define _3DSTATE_DEFAULT_SPECULAR ((0x3<<29)|(0x1d<<24)|(0x9a<<16))
#define MI_FLUSH ((0<<29)|(4<<23))
#define FLUSH_MAP_CACHE (1<<0)
#define FLUSH_RENDER_CACHE (1<<1)
#define MI_FLUSH ((0<<29)|(4<<23))
#define FLUSH_MAP_CACHE (1<<0)
#define INHIBIT_FLUSH_RENDER_CACHE (1<<2)
#endif

View File

@@ -36,6 +36,7 @@
#include "texmem.h"
#include "intel_fbo.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
@@ -48,7 +49,7 @@ static void
i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
GLuint mask)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int test = intel_translate_compare_func( func );
mask = mask & 0xff;
@@ -73,7 +74,7 @@ i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
static void
i915StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
if (INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask);
@@ -91,7 +92,7 @@ static void
i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
GLenum zpass)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int fop = intel_translate_stencil_op(fail);
int dfop = intel_translate_stencil_op(zfail);
int dpop = intel_translate_stencil_op(zpass);
@@ -116,7 +117,7 @@ i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int test = intel_translate_compare_func( func );
GLubyte refByte;
@@ -137,7 +138,7 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
*/
static void i915EvalLogicOpBlendState(GLcontext *ctx)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
@@ -157,7 +158,7 @@ static void i915EvalLogicOpBlendState(GLcontext *ctx)
static void i915BlendColor(GLcontext *ctx, const GLfloat color[4])
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
GLubyte r, g, b, a;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -194,7 +195,7 @@ static GLuint translate_blend_equation( GLenum mode )
static void i915UpdateBlendState( GLcontext *ctx )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &
~(IAB_SRC_FACTOR_MASK |
IAB_DST_FACTOR_MASK |
@@ -261,7 +262,7 @@ static void i915BlendEquationSeparate(GLcontext *ctx, GLenum eqRGB,
static void i915DepthFunc(GLcontext *ctx, GLenum func)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int test = intel_translate_compare_func( func );
if (INTEL_DEBUG&DEBUG_DRI)
@@ -274,7 +275,7 @@ static void i915DepthFunc(GLcontext *ctx, GLenum func)
static void i915DepthMask(GLcontext *ctx, GLboolean flag)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
if (INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag);
@@ -295,7 +296,7 @@ static void i915DepthMask(GLcontext *ctx, GLboolean flag)
*/
static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
const GLubyte *m = mask;
GLubyte p[4];
int i,j,k;
@@ -348,15 +349,14 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
GLsizei w, GLsizei h)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
intelScreenPrivate *screen = i915->intel.intelScreen;
struct i915_context *i915 = I915_CONTEXT(ctx);
int x1, y1, x2, y2;
if (!i915->intel.driDrawable)
if (!ctx->DrawBuffer)
return;
x1 = x;
y1 = i915->intel.driDrawable->h - (y + h);
y1 = ctx->DrawBuffer->Height - (y + h);
x2 = x + w - 1;
y2 = y1 + h - 1;
@@ -364,16 +364,10 @@ static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
x, y, w, h);
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
if (x2 < 0) x2 = 0;
if (y2 < 0) y2 = 0;
if (x2 >= screen->width) x2 = screen->width-1;
if (y2 >= screen->height) y2 = screen->height-1;
if (x1 >= screen->width) x1 = screen->width-1;
if (y1 >= screen->height) y1 = screen->height-1;
x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1);
y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1);
x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1);
y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1);
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
@@ -382,7 +376,7 @@ static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
static void i915LogicOp(GLcontext *ctx, GLenum opcode)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int tmp = intel_translate_logic_op(opcode);
if (INTEL_DEBUG&DEBUG_DRI)
@@ -397,7 +391,7 @@ static void i915LogicOp(GLcontext *ctx, GLenum opcode)
static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
GLuint mode;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -425,7 +419,7 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
{
i915ContextPtr i915 = I915_CONTEXT( ctx );
struct i915_context *i915 = I915_CONTEXT( ctx );
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK;
int width;
@@ -444,7 +438,7 @@ static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
static void i915PointSize(GLcontext *ctx, GLfloat size)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK;
GLint point_size = (int)size;
@@ -469,7 +463,7 @@ static void i915ColorMask(GLcontext *ctx,
GLboolean r, GLboolean g,
GLboolean b, GLboolean a)
{
i915ContextPtr i915 = I915_CONTEXT( ctx );
struct i915_context *i915 = I915_CONTEXT( ctx );
GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -490,7 +484,7 @@ static void update_specular( GLcontext *ctx )
{
/* A hack to trigger the rebuild of the fragment program.
*/
INTEL_CONTEXT(ctx)->NewGLState |= _NEW_TEXTURE;
intel_context(ctx)->NewGLState |= _NEW_TEXTURE;
I915_CONTEXT(ctx)->tex_program.translated = 0;
}
@@ -507,7 +501,7 @@ static void i915LightModelfv(GLcontext *ctx, GLenum pname,
static void i915ShadeModel(GLcontext *ctx, GLenum mode)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
if (mode == GL_SMOOTH) {
@@ -526,7 +520,7 @@ static void i915ShadeModel(GLcontext *ctx, GLenum mode)
*/
void i915_update_fog( GLcontext *ctx )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
GLenum mode;
GLboolean enabled;
GLboolean try_pixel_fog;
@@ -619,7 +613,7 @@ void i915_update_fog( GLcontext *ctx )
static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
switch (pname) {
case GL_FOG_COORDINATE_SOURCE_EXT:
@@ -671,7 +665,7 @@ static void i915Hint(GLcontext *ctx, GLenum target, GLenum state)
static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
switch(cap) {
case GL_TEXTURE_2D:
@@ -699,7 +693,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
/* Logicop doesn't seem to work at 16bpp:
*/
if (i915->intel.intelScreen->cpp == 2)
if (i915->intel.intelScreen->cpp == 2) /* XXX FBO fix */
FALLBACK( &i915->intel, I915_FALLBACK_LOGICOP, state );
break;
@@ -750,16 +744,24 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
break;
case GL_STENCIL_TEST:
if (i915->intel.hw_stencil) {
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
if (state)
i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE);
else
i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE);
} else {
FALLBACK( &i915->intel, I915_FALLBACK_STENCIL, state );
{
GLboolean hw_stencil = GL_FALSE;
if (ctx->DrawBuffer) {
struct intel_renderbuffer *irbStencil
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
hw_stencil = (irbStencil && irbStencil->region);
}
if (hw_stencil) {
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
if (state)
i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE);
else
i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE);
} else {
FALLBACK( &i915->intel, I915_FALLBACK_STENCIL, state );
}
}
break;
@@ -785,7 +787,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
}
static void i915_init_packets( i915ContextPtr i915 )
static void i915_init_packets( struct i915_context *i915 )
{
intelScreenPrivate *screen = i915->intel.intelScreen;
@@ -808,7 +810,7 @@ static void i915_init_packets( i915ContextPtr i915 )
i915->state.Ctx[I915_CTXREG_LIS4] = 0;
i915->state.Ctx[I915_CTXREG_LIS5] = 0;
if (screen->cpp == 2)
if (screen->cpp == 2) /* XXX FBO fix */
i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE;
@@ -823,7 +825,6 @@ static void i915_init_packets( i915ContextPtr i915 )
ENABLE_STENCIL_WRITE_MASK |
STENCIL_WRITE_MASK(0xff));
i915->state.Ctx[I915_CTXREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
IAB_MODIFY_ENABLE |
IAB_MODIFY_FUNC |
@@ -857,24 +858,24 @@ static void i915_init_packets( i915ContextPtr i915 )
{
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
/* XXX FBO: remove this? Also get set in i915_set_draw_region() */
i915->state.Buffer[I915_DESTREG_CBUFADDR1] =
(BUF_3D_ID_COLOR_BACK |
BUF_3D_PITCH(screen->front.pitch * screen->cpp) |
BUF_3D_PITCH(screen->front.pitch * screen->cpp) | /* XXX FBO fix */
BUF_3D_USE_FENCE);
i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
/* XXX FBO: remove this? Also get set in i915_set_draw_region() */
i915->state.Buffer[I915_DESTREG_DBUFADDR1] =
(BUF_3D_ID_DEPTH |
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) |
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | /* XXX FBO fix */
BUF_3D_USE_FENCE);
i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depth.offset;
i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
/* XXX FBO: remove this? Also get set in i915_set_draw_region() */
#if 0 /* seems we don't need this */
switch (screen->fbFormat) {
case DV_PF_555:
case DV_PF_565:
i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
@@ -893,6 +894,8 @@ static void i915_init_packets( i915ContextPtr i915 )
DEPTH_FRMT_24_FIXED_8_OTHER);
break;
}
#endif
i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
DISABLE_SCISSOR_RECT);
i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD;
@@ -901,13 +904,27 @@ static void i915_init_packets( i915ContextPtr i915 )
}
#if 0
{
I915_STATECHANGE(i915, I915_UPLOAD_DEFAULTS);
i915->state.Default[I915_DEFREG_C0] = _3DSTATE_DEFAULT_DIFFUSE;
i915->state.Default[I915_DEFREG_C1] = 0;
i915->state.Default[I915_DEFREG_S0] = _3DSTATE_DEFAULT_SPECULAR;
i915->state.Default[I915_DEFREG_S1] = 0;
i915->state.Default[I915_DEFREG_Z0] = _3DSTATE_DEFAULT_Z;
i915->state.Default[I915_DEFREG_Z1] = 0;
}
#endif
/* These will be emitted every at the head of every buffer, unless
* we get hardware contexts working.
*/
i915->state.active = (I915_UPLOAD_PROGRAM |
I915_UPLOAD_STIPPLE |
I915_UPLOAD_CTX |
I915_UPLOAD_BUFFERS);
I915_UPLOAD_STIPPLE |
I915_UPLOAD_CTX |
I915_UPLOAD_BUFFERS |
I915_UPLOAD_INVARIENT);
}
void i915InitStateFunctions( struct dd_function_table *functions )
@@ -937,7 +954,7 @@ void i915InitStateFunctions( struct dd_function_table *functions )
}
void i915InitState( i915ContextPtr i915 )
void i915InitState( struct i915_context *i915 )
{
GLcontext *ctx = &i915->intel.ctx;

View File

@@ -45,76 +45,10 @@
/**
* Allocate space for and load the mesa images into the texture memory block.
* This will happen before drawing with a new texture, or drawing with a
* texture after it was swapped out or teximaged again.
*/
intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj )
{
i915TextureObjectPtr t = CALLOC_STRUCT( i915_texture_object );
if ( !t )
return NULL;
texObj->DriverData = t;
t->intel.base.tObj = texObj;
t->intel.dirty = I915_UPLOAD_TEX_ALL;
make_empty_list( &t->intel.base );
return &t->intel;
}
static void i915TexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_WRAP_R:
case GL_TEXTURE_BORDER_COLOR:
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
case GL_TEXTURE_COMPARE_MODE:
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
case GL_TEXTURE_COMPARE_FUNC:
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* The i915 and its successors can do a lot of this without
* reloading the textures. A project for someone?
*/
intelFlush( ctx );
driSwapOutTextureObject( (driTextureObject *) t );
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
default:
return;
}
}
static void i915TexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
i915ContextPtr i915 = I915_CONTEXT( ctx );
GLuint unit = ctx->Texture.CurrentUnit;
struct i915_context *i915 = I915_CONTEXT( ctx );
switch (pname) {
case GL_TEXTURE_ENV_COLOR: /* Should be a tracked param */
@@ -139,13 +73,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_LOD_BIAS: {
int b = (int) ((*param) * 16.0);
GLuint unit = ctx->Texture.CurrentUnit;
GLint b = (int) ((*param) * 16.0);
if (b > 255) b = 255;
if (b < -256) b = -256;
I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK;
i915->state.Tex[unit][I915_TEXREG_SS2] |=
((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
i915->lodbias_ss2[unit] = ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
break;
}
@@ -156,15 +89,8 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
static void i915BindTexture( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj )
struct gl_texture_object *texobj )
{
i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData;
if (tex->lastTarget != texObj->Target) {
tex->intel.dirty = I915_UPLOAD_TEX_ALL;
tex->lastTarget = texObj->Target;
}
/* Need this if image format changes between bound textures.
* Could try and shortcircuit by checking for differences in
* state between incoming and outgoing textures:
@@ -178,5 +104,4 @@ void i915InitTextureFuncs( struct dd_function_table *functions )
{
functions->BindTexture = i915BindTexture;
functions->TexEnv = i915TexEnv;
functions->TexParameter = i915TexParameter;
}

View File

@@ -0,0 +1,338 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/* Code to layout images in a mipmap tree for i915 and i945
* respectively.
*/
#include "intel_mipmap_tree.h"
#include "macros.h"
static GLint initial_offsets[6][2] = { {0,0},
{0,2},
{1,0},
{1,2},
{1,1},
{1,3} };
static GLint step_offsets[6][2] = { {0,2},
{0,2},
{-1,2},
{-1,2},
{-1,1},
{-1,1} };
static GLuint minify( GLuint d )
{
return MAX2(1, d>>1);
}
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
{
GLint i;
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP: {
const GLuint dim = mt->width0;
GLuint face;
/* double pitch for cube layouts */
mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
mt->total_height = dim * 4;
for ( face = 0 ; face < 6 ; face++) {
GLuint x = initial_offsets[face][0] * dim;
GLuint y = initial_offsets[face][1] * dim;
GLuint d = dim;
for (i = mt->first_level; i <= mt->last_level; i++) {
intel_miptree_set_image_offset(mt, face, i,
x, y,
d, d, 1);
if (d == 0)
_mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n",
face, i, mt->first_level, mt->last_level);
d >>= 1;
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
}
}
break;
}
case GL_TEXTURE_3D: {
GLuint width = mt->width0;
GLuint height = mt->height0;
GLuint depth = mt->depth0;
/* Calculate the size of a single slice.
*/
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
/* XXX: hardware expects/requires 9 levels at minimum.
*/
for ( i = mt->first_level ; i <= MAX2(8, mt->last_level) ; i++ ) {
intel_miptree_set_image_offset(mt, 0, i,
0, mt->total_height,
width, height, depth);
mt->total_height += MAX2(2, height);
width = minify(width);
height = minify(height);
depth = minify(depth);
}
/* Fixup depth_image_stride:
*/
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
mt->offset[0][i].depth_image_stride = mt->total_height * mt->pitch * mt->cpp;
}
/* Multiply slice size by texture depth for total size. It's
* remarkable how wasteful of memory the i915 texture layouts
* are. They are largely fixed in the i945.
*/
mt->total_height *= mt->depth0;
break;
}
default: {
GLuint width = mt->width0;
GLuint height = mt->height0;
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
intel_miptree_set_image_offset(mt, 0, i,
0, mt->total_height,
width, height, 1);
if (mt->compressed)
mt->total_height += MAX2(1, height/4);
else
mt->total_height += MAX2(2, height);
width = minify(width);
height = minify(height);
}
break;
}
}
DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
mt->pitch,
mt->total_height,
mt->cpp,
mt->pitch * mt->total_height * mt->cpp );
return GL_TRUE;
}
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt )
{
GLint i;
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP: {
const GLuint dim = mt->width0;
GLuint face;
/* Depending on the size of the largest images, pitch can be
* determined either by the old-style packing of cubemap faces,
* or the final row of 4x4, 2x2 and 1x1 faces below this.
*/
if (dim > 32)
mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
else
mt->pitch = 14 * 8;
mt->total_height = dim * 4 + 4;
for ( face = 0 ; face < 6 ; face++) {
GLuint x = initial_offsets[face][0] * dim;
GLuint y = initial_offsets[face][1] * dim;
GLuint d = dim;
if (dim == 4 && face >= 4) {
y = mt->total_height - 4;
x = (face - 4) * 8;
}
else if (dim < 4) {
y = mt->total_height - 4;
x = face * 8;
}
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
intel_miptree_set_image_offset(mt, face, i,
x, y,
d, d, 1);
d >>= 1;
switch (d) {
case 4:
switch (face) {
case FACE_POS_X:
case FACE_NEG_X:
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
break;
case FACE_POS_Y:
case FACE_NEG_Y:
y += 12;
x -= 8;
break;
case FACE_POS_Z:
case FACE_NEG_Z:
y = mt->total_height - 4;
x = (face - 4) * 8;
break;
}
case 2:
y = mt->total_height - 4;
x = 16 + face * 8;
break;
case 1:
x += 48;
break;
default:
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
break;
}
}
}
break;
}
case GL_TEXTURE_3D: {
GLuint width = mt->width0;
GLuint height = mt->height0;
GLuint depth = mt->depth0;
GLuint depth_pack_pitch;
GLuint depth_packing = 0;
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
depth_pack_pitch = mt->pitch * mt->cpp;
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
intel_miptree_set_image_offset(mt, 0, i,
0, mt->total_height,
width, height, depth);
mt->total_height += MAX2(2, height) * MAX2((depth >> depth_packing), 1);
/* When alignment dominates, can't increase depth packing?
* Or does pitch grow??? What are the alignment constraints,
* anyway?
*/
if (depth_pack_pitch > 4) {
depth_packing++;
depth_pack_pitch >>= 2; /* KW: is this right?? */
}
width = minify(width);
height = minify(height);
depth = minify(depth);
/* XXX: Not sure how 3d textures work on i945 - where did
* t->depth_pitch get set in the old code. Did it ever work?
* Fix up later.
*/
}
break;
}
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB: {
GLuint x = 0;
GLuint y = 0;
GLuint width = mt->width0;
GLuint height = mt->height0;
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
intel_miptree_set_image_offset(mt, 0, i,
x, y,
width, height, 1);
/* LPT change: step right after second mipmap.
*/
if (i == 1)
x += mt->pitch / 2;
else {
GLuint img_height;
if (mt->compressed)
img_height = MAX2(1, height/4);
else
img_height = MAX2(2, height);
y += img_height;
}
/* Because the images are packed better, the final offset
* might not be the maximal one:
*/
mt->total_height = MAX2(mt->total_height, y);
width = minify(width);
height = minify(height);
}
break;
}
default:
_mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()");
}
DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
mt->pitch,
mt->total_height,
mt->cpp,
mt->pitch * mt->total_height * mt->cpp );
return GL_TRUE;
}

View File

@@ -536,7 +536,7 @@ static void emit_program_fini( struct i915_fragment_program *p )
}
static void i915EmitTextureProgram( i915ContextPtr i915 )
static void i915EmitTextureProgram( struct i915_context *i915 )
{
GLcontext *ctx = &i915->intel.ctx;
struct i915_fragment_program *p = &i915->tex_program;
@@ -570,9 +570,9 @@ static void i915EmitTextureProgram( i915ContextPtr i915 )
}
void i915ValidateTextureProgram( i915ContextPtr i915 )
void i915ValidateTextureProgram( struct i915_context *i915 )
{
intelContextPtr intel = &i915->intel;
struct intel_context *intel = &i915->intel;
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
@@ -639,7 +639,8 @@ void i915ValidateTextureProgram( i915ContextPtr i915 )
*/
if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
int k;
I915_STATECHANGE( i915, I915_UPLOAD_CTX );
i915->tex_program.translated = 0;
@@ -657,7 +658,8 @@ void i915ValidateTextureProgram( i915ContextPtr i915 )
i915->state.Ctx[I915_CTXREG_LIS2] = s2;
i915->state.Ctx[I915_CTXREG_LIS4] = s4;
assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size ));
k = intel->vtbl.check_vertex_size( intel, intel->vertex_size );
assert(k);
}
if (!i915->tex_program.translated ||

File diff suppressed because it is too large Load Diff

View File

@@ -37,14 +37,16 @@
#include "tnl/t_vertex.h"
#include "intel_batchbuffer.h"
#include "intel_tex.h"
#include "intel_regions.h"
#include "i915_reg.h"
#include "i915_context.h"
static void i915_render_start( intelContextPtr intel )
static void i915_render_start( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_context *i915 = i915_context(&intel->ctx);
if (ctx->FragmentProgram._Active)
i915ValidateFragmentProgram( i915 );
@@ -53,42 +55,42 @@ static void i915_render_start( intelContextPtr intel )
}
static void i915_reduced_primitive_state( intelContextPtr intel,
static void i915_reduced_primitive_state( struct intel_context *intel,
GLenum rprim )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
struct i915_context *i915 = i915_context(&intel->ctx);
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
st1 &= ~ST1_ENABLE;
st1 &= ~ST1_ENABLE;
switch (rprim) {
case GL_TRIANGLES:
if (intel->ctx.Polygon.StippleFlag &&
intel->hw_stipple)
st1 |= ST1_ENABLE;
break;
case GL_LINES:
case GL_POINTS:
default:
break;
}
switch (rprim) {
case GL_TRIANGLES:
if (intel->ctx.Polygon.StippleFlag &&
intel->hw_stipple)
st1 |= ST1_ENABLE;
break;
case GL_LINES:
case GL_POINTS:
default:
break;
}
i915->intel.reduced_primitive = rprim;
i915->intel.reduced_primitive = rprim;
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
i915->state.Stipple[I915_STPREG_ST1] = st1;
}
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
i915->state.Stipple[I915_STPREG_ST1] = st1;
}
}
/* Pull apart the vertex format registers and figure out how large a
* vertex is supposed to be.
*/
static GLboolean i915_check_vertex_size( intelContextPtr intel,
static GLboolean i915_check_vertex_size( struct intel_context *intel,
GLuint expected )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_context *i915 = i915_context(&intel->ctx);
int lis2 = i915->current->Ctx[I915_CTXREG_LIS2];
int lis4 = i915->current->Ctx[I915_CTXREG_LIS4];
int i, sz = 0;
@@ -132,11 +134,11 @@ static GLboolean i915_check_vertex_size( intelContextPtr intel,
}
static void i915_emit_invarient_state( intelContextPtr intel )
static void i915_emit_invarient_state( struct intel_context *intel )
{
BATCH_LOCALS;
BEGIN_BATCH( 200 );
BEGIN_BATCH( 200, 0 );
OUT_BATCH(_3DSTATE_AA_CMD |
AA_LINE_ECAAR_WIDTH_ENABLE |
@@ -204,21 +206,15 @@ static void i915_emit_invarient_state( intelContextPtr intel )
}
#define emit( intel, state, size ) \
do { \
int k; \
BEGIN_BATCH( (size) / sizeof(GLuint)); \
for (k = 0 ; k < (size) / sizeof(GLuint) ; k++) \
OUT_BATCH((state)[k]); \
ADVANCE_BATCH(); \
} while (0);
#define emit(intel, state, size ) \
intel_batchbuffer_data(intel->batch, state, size, 0 )
/* Push the state into the sarea and/or texture memory.
*/
static void i915_emit_state( intelContextPtr intel )
static void i915_emit_state( struct intel_context *intel )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_context *i915 = i915_context(&intel->ctx);
struct i915_hw_state *state = i915->current;
int i;
GLuint dirty;
@@ -233,27 +229,51 @@ static void i915_emit_state( intelContextPtr intel )
dirty = state->active & ~state->emitted;
if (VERBOSE)
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty);
if (dirty & I915_UPLOAD_INVARIENT) {
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n");
i915_emit_invarient_state( intel );
}
if (dirty & I915_UPLOAD_CTX) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");
emit( i915, state->Ctx, sizeof(state->Ctx) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n");
emit(intel, state->Ctx, sizeof(state->Ctx) );
}
if (dirty & I915_UPLOAD_BUFFERS) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
emit( i915, state->Buffer, sizeof(state->Buffer) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
BEGIN_BATCH(I915_DEST_SETUP_SIZE+2, 0);
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]);
OUT_RELOC(state->draw_region->buffer, DRM_MM_TT|DRM_MM_WRITE,
state->draw_region->draw_offset);
if (state->depth_region) {
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]);
OUT_RELOC(state->depth_region->buffer, DRM_MM_TT|DRM_MM_WRITE,
state->depth_region->draw_offset);
}
OUT_BATCH(state->Buffer[I915_DESTREG_DV0]);
OUT_BATCH(state->Buffer[I915_DESTREG_DV1]);
OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]);
OUT_BATCH(state->Buffer[I915_DESTREG_SR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_SR1]);
OUT_BATCH(state->Buffer[I915_DESTREG_SR2]);
ADVANCE_BATCH();
}
if (dirty & I915_UPLOAD_STIPPLE) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");
emit( i915, state->Stipple, sizeof(state->Stipple) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");
emit(intel, state->Stipple, sizeof(state->Stipple) );
}
if (dirty & I915_UPLOAD_FOG) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_FOG:\n");
emit( i915, state->Fog, sizeof(state->Fog) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_FOG:\n");
emit(intel, state->Fog, sizeof(state->Fog) );
}
/* Combine all the dirty texture state into a single command to
@@ -266,18 +286,29 @@ static void i915_emit_state( intelContextPtr intel )
if (dirty & I915_UPLOAD_TEX(i))
nr++;
BEGIN_BATCH(2+nr*3);
BEGIN_BATCH(2+nr*3, 0);
OUT_BATCH(_3DSTATE_MAP_STATE | (3*nr));
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
for (i = 0 ; i < I915_TEX_UNITS ; i++)
if (dirty & I915_UPLOAD_TEX(i)) {
OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]);
if (state->tex_buffer[i]) {
OUT_RELOC(state->tex_buffer[i],
DRM_MM_TT|DRM_MM_READ,
state->tex_offset[i]);
}
else {
assert(i == 0);
assert(state == &i915->meta);
OUT_BATCH(0);
}
OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]);
OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]);
}
ADVANCE_BATCH();
BEGIN_BATCH(2+nr*3);
BEGIN_BATCH(2+nr*3, 0);
OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3*nr));
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
for (i = 0 ; i < I915_TEX_UNITS ; i++)
@@ -290,64 +321,132 @@ static void i915_emit_state( intelContextPtr intel )
}
if (dirty & I915_UPLOAD_CONSTANTS) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");
emit( i915, state->Constant, state->ConstantSize * sizeof(GLuint) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");
emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint) );
}
if (dirty & I915_UPLOAD_PROGRAM) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");
assert((state->Program[0] & 0x1ff)+2 == state->ProgramSize);
emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) );
if (VERBOSE)
emit(intel, state->Program, state->ProgramSize * sizeof(GLuint) );
if (INTEL_DEBUG & DEBUG_STATE)
i915_disassemble_program( state->Program, state->ProgramSize );
}
state->emitted |= dirty;
}
static void i915_destroy_context( intelContextPtr intel )
static void i915_destroy_context( struct intel_context *intel )
{
_tnl_free_vertices(&intel->ctx);
}
static void i915_set_draw_offset( intelContextPtr intel, int offset )
/**
* Set the drawing regions for the color and depth/stencil buffers.
* This involves setting the pitch, cpp and buffer ID/location.
* Also set pixel format for color and Z rendering
* Used for setting both regular and meta state.
*/
void
i915_state_draw_region(struct intel_context *intel,
struct i915_hw_state *state,
struct intel_region *color_region,
struct intel_region *depth_region)
{
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_context *i915 = i915_context(&intel->ctx);
GLuint value;
ASSERT(state == &i915->state || state == &i915->meta);
if (state->draw_region != color_region) {
intel_region_release(intel, &state->draw_region);
intel_region_reference(&state->draw_region, color_region);
}
if (state->depth_region != depth_region) {
intel_region_release(intel, &state->depth_region);
intel_region_reference(&state->depth_region, depth_region);
}
/*
* Set stride/cpp values
*/
if (color_region) {
state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
state->Buffer[I915_DESTREG_CBUFADDR1] =
(BUF_3D_ID_COLOR_BACK |
BUF_3D_PITCH(color_region->pitch * color_region->cpp) |
BUF_3D_USE_FENCE);
}
if (depth_region) {
state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
state->Buffer[I915_DESTREG_DBUFADDR1] =
(BUF_3D_ID_DEPTH |
BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) |
BUF_3D_USE_FENCE);
}
/*
* Compute/set I915_DESTREG_DV1 value
*/
value = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
LOD_PRECLAMP_OGL |
TEX_DEFAULT_COLOR_OGL);
if (color_region && color_region->cpp == 4) {
value |= DV_PF_8888;
}
else {
value |= (DITHER_FULL_ALWAYS | DV_PF_565);
}
if (depth_region && depth_region->cpp == 4) {
value |= DEPTH_FRMT_24_FIXED_8_OTHER;
}
else {
value |= DEPTH_FRMT_16_FIXED;
}
state->Buffer[I915_DESTREG_DV1] = value;
I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS );
i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset;
}
static void i915_lost_hardware( intelContextPtr intel )
{
I915_CONTEXT(intel)->state.emitted = 0;
}
static void i915_emit_flush( intelContextPtr intel )
{
BATCH_LOCALS;
BEGIN_BATCH(2);
OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE );
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void i915InitVtbl( i915ContextPtr i915 )
static void
i915_set_draw_region(struct intel_context *intel,
struct intel_region *color_region,
struct intel_region *depth_region)
{
struct i915_context *i915 = i915_context(&intel->ctx);
i915_state_draw_region(intel, &i915->state, color_region, depth_region);
}
static void i915_lost_hardware( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
i915->state.emitted = 0;
}
static GLuint i915_flush_cmd( void )
{
return MI_FLUSH | FLUSH_MAP_CACHE;
}
void i915InitVtbl( struct i915_context *i915 )
{
i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj;
i915->intel.vtbl.check_vertex_size = i915_check_vertex_size;
i915->intel.vtbl.clear_with_tris = i915ClearWithTris;
i915->intel.vtbl.destroy = i915_destroy_context;
i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state;
i915->intel.vtbl.emit_state = i915_emit_state;
i915->intel.vtbl.lost_hardware = i915_lost_hardware;
i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state;
i915->intel.vtbl.render_start = i915_render_start;
i915->intel.vtbl.set_draw_offset = i915_set_draw_offset;
i915->intel.vtbl.set_draw_region = i915_set_draw_region;
i915->intel.vtbl.update_texture_state = i915UpdateTextureState;
i915->intel.vtbl.emit_flush = i915_emit_flush;
i915->intel.vtbl.flush_cmd = i915_flush_cmd;
}

View File

@@ -1,6 +1,6 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,664 +25,270 @@
*
**************************************************************************/
#include <stdio.h>
#include <errno.h>
#include "mtypes.h"
#include "context.h"
#include "enums.h"
#include "intel_reg.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_bufmgr.h"
/* ================================================================
* Performance monitoring functions
/* Relocations in kernel space:
* - pass dma buffer seperately
* - memory manager knows how to patch
* - pass list of dependent buffers
* - pass relocation list
*
* Either:
* - get back an offset for buffer to fire
* - memory manager knows how to fire buffer
*
* Really want the buffer to be AGP and pinned.
*
*/
static void intel_fill_box( intelContextPtr intel,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLubyte r, GLubyte g, GLubyte b )
/* Cliprect fence: The highest fence protecting a dma buffer
* containing explicit cliprect information. Like the old drawable
* lock but irq-driven. X server must wait for this fence to expire
* before changing cliprects [and then doing sw rendering?]. For
* other dma buffers, the scheduler will grab current cliprect info
* and mix into buffer. X server must hold the lock while changing
* cliprects??? Make per-drawable. Need cliprects in shared memory
* -- beats storing them with every cmd buffer in the queue.
*
* ==> X server must wait for this fence to expire before touching the
* framebuffer with new cliprects.
*
* ==> Cliprect-dependent buffers associated with a
* cliprect-timestamp. All of the buffers associated with a timestamp
* must go to hardware before any buffer with a newer timestamp.
*
* ==> Dma should be queued per-drawable for correct X/GL
* synchronization. Or can fences be used for this?
*
* Applies to: Blit operations, metaops, X server operations -- X
* server automatically waits on its own dma to complete before
* modifying cliprects ???
*/
static void intel_dump_batchbuffer( GLuint offset,
GLuint *ptr,
GLuint count )
{
intelEmitFillBlitLocked( intel,
intel->intelScreen->cpp,
intel->intelScreen->back.pitch,
intel->intelScreen->front.offset,
x, y, w, h,
INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
r,g,b,0xff));
}
static void intel_draw_performance_boxes( intelContextPtr intel )
{
/* Purple box for page flipping
*/
if ( intel->perf_boxes & I830_BOX_FLIP )
intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
/* Red box if we have to wait for idle at any point
*/
if ( intel->perf_boxes & I830_BOX_WAIT )
intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
/* Blue box: lost context?
*/
if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )
intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
/* Yellow box for texture swaps
*/
if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )
intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
/* Green box if hardware never idles (as far as we can tell)
*/
if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )
intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
/* Draw bars indicating number of buffers allocated
* (not a great measure, easily confused)
*/
#if 0
if (intel->dma_used) {
int bar = intel->dma_used / 10240;
if (bar > 100) bar = 100;
if (bar < 1) bar = 1;
intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
intel->dma_used = 0;
}
#endif
intel->perf_boxes = 0;
int i;
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count/4);
for (i = 0; i < count/4; i += 4)
fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n",
offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]);
fprintf(stderr, "END BATCH\n\n\n");
}
static int bad_prim_vertex_nr( int primitive, int nr )
static void intel_batchbuffer_reset( struct intel_batchbuffer *batch )
{
switch (primitive & PRIM3D_MASK) {
case PRIM3D_POINTLIST:
return nr < 1;
case PRIM3D_LINELIST:
return (nr & 1) || nr == 0;
case PRIM3D_LINESTRIP:
return nr < 2;
case PRIM3D_TRILIST:
case PRIM3D_RECTLIST:
return nr % 3 || nr == 0;
case PRIM3D_POLY:
case PRIM3D_TRIFAN:
case PRIM3D_TRISTRIP:
case PRIM3D_TRISTRIP_RVRSE:
return nr < 3;
default:
return 1;
}
bmBufferData(batch->bm,
batch->buffer,
BATCH_SZ,
NULL,
0);
if (!batch->list)
batch->list = bmNewBufferList();
drmMMClearBufList(batch->list);
batch->list_count = 0;
batch->nr_relocs = 0;
batch->flags = 0;
bmAddBuffer( batch->bm,
batch->list,
batch->buffer,
DRM_MM_TT,
NULL,
&batch->offset[batch->list_count++]);
batch->map = bmMapBuffer(batch->bm, batch->buffer, DRM_MM_WRITE);
batch->ptr = batch->map;
}
static void intel_flush_inline_primitive( GLcontext *ctx )
/*======================================================================
* Public functions
*/
struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
GLuint used = intel->batch.ptr - intel->prim.start_ptr;
GLuint vertcount;
struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
assert(intel->prim.primitive != ~0);
batch->intel = intel;
batch->bm = intel->bm;
if (1) {
/* Check vertex size against the vertex we're specifying to
* hardware. If it's wrong, ditch the primitive.
*/
if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))
goto do_discard;
bmGenBuffers(intel->bm, 1, &batch->buffer, BM_BATCHBUFFER);
batch->last_fence = bmInitFence(batch->bm);
intel_batchbuffer_reset( batch );
return batch;
}
vertcount = (used - 4)/ (intel->vertex_size * 4);
void intel_batchbuffer_free( struct intel_batchbuffer *batch )
{
if (batch->map)
bmUnmapBuffer(batch->bm, batch->buffer);
free(batch);
}
if (!vertcount)
goto do_discard;
/* TODO: Push this whole function into bufmgr.
*/
static void do_flush_locked( struct intel_batchbuffer *batch,
GLuint used,
GLboolean ignore_cliprects,
GLboolean allow_unlock)
{
GLuint *ptr;
GLuint i;
bmValidateBufferList( batch->bm,
batch->list,
DRM_MM_TT );
/* Apply the relocations. This nasty map indicates to me that the
* whole task should be done internally by the memory manager, and
* that dma buffers probably need to be pinned within agp space.
*/
ptr = (GLuint *)bmMapBuffer(batch->bm, batch->buffer, DRM_MM_WRITE);
for (i = 0; i < batch->nr_relocs; i++) {
struct buffer_reloc *r = &batch->reloc[i];
if (vertcount * intel->vertex_size * 4 != used - 4) {
fprintf(stderr, "vertex size confusion %d %d\n", used,
intel->vertex_size * vertcount * 4);
goto do_discard;
}
if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
vertcount);
goto do_discard;
}
assert(r->elem < batch->list_count);
ptr[r->offset/4] = batch->offset[r->elem] + r->delta;
}
if (used < 8)
goto do_discard;
if (INTEL_DEBUG & DEBUG_DMA)
intel_dump_batchbuffer( 0, ptr, used );
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
intel->prim.primitive |
(used/4-2));
goto finished;
bmUnmapBuffer(batch->bm, batch->buffer);
do_discard:
intel->batch.ptr -= used;
intel->batch.space += used;
assert(intel->batch.space >= 0);
finished:
intel->prim.primitive = ~0;
intel->prim.start_ptr = 0;
intel->prim.flush = 0;
}
/* Emit a primitive referencing vertices in a vertex buffer.
*/
void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
{
BATCH_LOCALS;
if (0)
fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
/* Finish any in-progress primitive:
/* Fire the batch buffer, which was uploaded above:
*/
INTEL_FIREVERTICES( intel );
/* Emit outstanding state:
*/
intel->vtbl.emit_state( intel );
/* Make sure there is some space in this buffer:
*/
if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space)
intelFlushBatch(intel, GL_TRUE);
#if 1
if (((int)intel->batch.ptr) & 0x4) {
BEGIN_BATCH(1);
OUT_BATCH(0);
ADVANCE_BATCH();
}
intel_batch_ioctl(batch->intel,
batch->offset[0],
used,
ignore_cliprects,
allow_unlock);
#endif
/* Emit a slot which will be filled with the inline primitive
* command later.
*/
BEGIN_BATCH(2);
OUT_BATCH( 0 );
intel->prim.start_ptr = batch_ptr;
intel->prim.primitive = prim;
intel->prim.flush = intel_flush_inline_primitive;
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void intelRestartInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
intel_flush_inline_primitive( &intel->ctx );
if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
intelStartInlinePrimitive( intel, prim );
}
void intelWrapInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
intel_flush_inline_primitive( &intel->ctx );
intelFlushBatch(intel, GL_TRUE);
intelStartInlinePrimitive( intel, prim );
}
/* Emit a primitive with space for inline vertices.
*/
GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
int primitive,
int dwords,
int vertex_size )
{
GLuint *tmp = 0;
BATCH_LOCALS;
if (0)
fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
/* Emit outstanding state:
*/
intel->vtbl.emit_state( intel );
if (1) {
int used = dwords * 4;
int vertcount;
/* Check vertex size against the vertex we're specifying to
* hardware. If it's wrong, ditch the primitive.
*/
if (!intel->vtbl.check_vertex_size( intel, vertex_size ))
goto do_discard;
vertcount = dwords / vertex_size;
if (dwords % vertex_size) {
fprintf(stderr, "did not request a whole number of vertices\n");
goto do_discard;
}
if (bad_prim_vertex_nr( primitive, vertcount )) {
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
goto do_discard;
}
if (used < 8)
goto do_discard;
}
/* Emit 3D_PRIMITIVE commands:
*/
BEGIN_BATCH(1 + dwords);
OUT_BATCH( _3DPRIMITIVE |
primitive |
(dwords-1) );
tmp = (GLuint *)batch_ptr;
batch_ptr += dwords * 4;
ADVANCE_BATCH();
do_discard:
return tmp;
}
/*
* Copy the back buffer to the front buffer.
*/
void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
{
intelContextPtr intel;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
intelScreenPrivate *intelScreen = intel->intelScreen;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *pbox = dPriv->pClipRects;
int pitch = intelScreen->front.pitch;
int cpp = intelScreen->cpp;
int i;
GLuint CMD, BR13;
BATCH_LOCALS;
switch(cpp) {
case 2:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
}
if (0)
intel_draw_performance_boxes( intel );
for (i = 0 ; i < nbox; i++, pbox++)
{
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
pbox->x2 > intelScreen->width ||
pbox->y2 > intelScreen->height)
continue;
batch->last_fence = bmFenceBufferList(batch->bm, batch->list);
if (!batch->intel->last_swap_fence_retired) {
int retired;
drmFence dFence = {0,batch->intel->last_swap_fence};
BEGIN_BATCH( 8);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
if (intel->sarea->pf_current_page == 0)
OUT_BATCH( intelScreen->front.offset );
else
OUT_BATCH( intelScreen->back.offset );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( BR13 & 0xffff );
if (intel->sarea->pf_current_page == 0)
OUT_BATCH( intelScreen->back.offset );
else
OUT_BATCH( intelScreen->front.offset );
ADVANCE_BATCH();
/*FIXME: Temporary fix for fence ageing
*
*/
if (!drmTestFence(batch->intel->driFd, dFence, 0, &retired)) {
batch->intel->last_swap_fence_retired = retired;
}
}
intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
UNLOCK_HARDWARE( intel );
}
}
void intelEmitFillBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color )
GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch )
{
GLuint BR13, CMD;
BATCH_LOCALS;
struct intel_context *intel = batch->intel;
GLuint used = batch->ptr - batch->map;
dst_pitch *= cpp;
if (used == 0)
return batch->last_fence;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
break;
default:
return;
/* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a
* performance drain that we would like to avoid.
*/
if (used & 4) {
((int *)batch->ptr)[0] = intel->vtbl.flush_cmd();
((int *)batch->ptr)[1] = 0;
((int *)batch->ptr)[2] = MI_BATCH_BUFFER_END;
used += 12;
}
else {
((int *)batch->ptr)[0] = intel->vtbl.flush_cmd() ;
((int *)batch->ptr)[1] = MI_BATCH_BUFFER_END;
used += 8;
}
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (y << 16) | x );
OUT_BATCH( ((y+h) << 16) | (x+w) );
OUT_BATCH( dst_offset );
OUT_BATCH( color );
ADVANCE_BATCH();
}
bmUnmapBuffer(batch->bm, batch->buffer);
batch->ptr = NULL;
batch->map = NULL;
/* Copy BitBlt
*/
void intelEmitCopyBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_offset,
GLshort src_x, GLshort src_y,
GLshort dst_x, GLshort dst_y,
GLshort w, GLshort h )
{
GLuint CMD, BR13;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
BATCH_LOCALS;
src_pitch *= cpp;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
return;
}
if (dst_y2 < dst_y ||
dst_x2 < dst_x) {
return;
}
BEGIN_BATCH( 12);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (dst_y << 16) | dst_x );
OUT_BATCH( (dst_y2 << 16) | dst_x2 );
OUT_BATCH( dst_offset );
OUT_BATCH( (src_y << 16) | src_x );
OUT_BATCH( src_pitch );
OUT_BATCH( src_offset );
ADVANCE_BATCH();
}
void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch)
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
intelScreenPrivate *intelScreen = intel->intelScreen;
GLuint clear_depth, clear_color;
GLint cx, cy;
GLint pitch = intelScreen->front.pitch;
GLint cpp = intelScreen->cpp;
GLint i;
GLuint BR13, CMD, D_CMD;
BATCH_LOCALS;
clear_color = intel->ClearColor;
clear_depth = 0;
if (flags & BUFFER_BIT_DEPTH) {
clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
}
if (flags & BUFFER_BIT_STENCIL) {
clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
}
switch(cpp) {
case 2:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD |
XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
D_CMD = XY_COLOR_BLT_CMD;
if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
break;
default:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
}
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
/* TODO: Just pass the relocation list and dma buffer up to the
* kernel.
*/
if (!intel->locked)
{
/* flip top to bottom */
cy = intel->driDrawable->h-cy1-ch;
cx = cx1 + intel->drawX;
cy += intel->drawY;
assert(!(batch->flags & INTEL_BATCH_NO_CLIPRECTS));
/* adjust for page flipping */
if ( intel->sarea->pf_current_page == 1 ) {
GLuint tmp = flags;
flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT;
if ( tmp & BUFFER_BIT_BACK_LEFT ) flags |= BUFFER_BIT_FRONT_LEFT;
}
for (i = 0 ; i < intel->numClipRects ; i++)
{
drm_clip_rect_t *box = &intel->pClipRects[i];
drm_clip_rect_t b;
if (!all) {
GLint x = box[i].x1;
GLint y = box[i].y1;
GLint w = box[i].x2 - x;
GLint h = box[i].y2 - y;
if (x < cx) w -= cx - x, x = cx;
if (y < cy) h -= cy - y, y = cy;
if (x + w > cx + cw) w = cx + cw - x;
if (y + h > cy + ch) h = cy + ch - y;
if (w <= 0) continue;
if (h <= 0) continue;
b.x1 = x;
b.y1 = y;
b.x2 = x + w;
b.y2 = y + h;
} else {
b = *box;
}
if (b.x1 > b.x2 ||
b.y1 > b.y2 ||
b.x2 > intelScreen->width ||
b.y2 > intelScreen->height)
continue;
if ( flags & BUFFER_BIT_FRONT_LEFT ) {
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->front.offset );
OUT_BATCH( clear_color );
ADVANCE_BATCH();
}
if ( flags & BUFFER_BIT_BACK_LEFT ) {
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->back.offset );
OUT_BATCH( clear_color );
ADVANCE_BATCH();
}
if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
BEGIN_BATCH( 6);
OUT_BATCH( D_CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->depth.offset );
OUT_BATCH( clear_depth );
ADVANCE_BATCH();
}
}
}
intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
UNLOCK_HARDWARE( intel );
}
void intelDestroyBatchBuffer( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (intel->alloc.ptr) {
intelFreeAGP( intel, intel->alloc.ptr );
intel->alloc.ptr = 0;
}
}
void intelInitBatchBuffer( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) {
intel->alloc.size = 8 * 1024;
intel->alloc.ptr = malloc( intel->alloc.size );
intel->alloc.offset = 0;
LOCK_HARDWARE(intel);
do_flush_locked(batch, used, GL_FALSE, GL_TRUE);
UNLOCK_HARDWARE(intel);
}
else {
switch (intel->intelScreen->deviceID) {
case PCI_CHIP_I865_G:
/* HW bug? Seems to crash if batchbuffer crosses 4k boundary.
*/
intel->alloc.size = 8 * 1024;
break;
default:
/* This is the smallest amount of memory the kernel deals with.
* We'd ideally like to make this smaller.
*/
intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
break;
}
intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
if (intel->alloc.ptr)
intel->alloc.offset =
intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
GLboolean ignore_cliprects = !(batch->flags & INTEL_BATCH_CLIPRECTS);
do_flush_locked(batch, used, ignore_cliprects, GL_FALSE);
}
if (!intel->alloc.ptr) {
FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1);
}
else {
intel->prim.flush = 0;
intel->vtbl.emit_invarient_state( intel );
/* Make sure this gets to the hardware, even if we have no cliprects:
*/
LOCK_HARDWARE( intel );
intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
UNLOCK_HARDWARE( intel );
}
/* Reset the buffer:
*/
intel_batchbuffer_reset( batch );
return batch->last_fence;
}
void intel_batchbuffer_finish( struct intel_batchbuffer *batch )
{
bmFinishFence(batch->bm,
intel_batchbuffer_flush(batch));
}
/* This is the only way buffers get added to the validate list.
*/
GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch,
GLuint buffer,
GLuint flags,
GLuint delta )
{
GLuint i;
assert(batch->nr_relocs <= MAX_RELOCS);
i = bmScanBufferList(batch->bm, batch->list, buffer);
if (i == -1) {
i = batch->list_count;
bmAddBuffer(batch->bm,
batch->list,
buffer,
flags,
NULL,
&batch->offset[batch->list_count++]);
}
{
struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++];
r->offset = batch->ptr - batch->map;
r->delta = delta;
r->elem = i;
}
batch->ptr += 4;
return GL_TRUE;
}
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
const void *data,
GLuint bytes,
GLuint flags)
{
assert((bytes & 3) == 0);
intel_batchbuffer_require_space(batch, bytes, flags);
__memcpy(batch->ptr, data, bytes);
batch->ptr += bytes;
}

View File

@@ -1,123 +1,124 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_BATCHBUFFER_H
#define INTEL_BATCHBUFFER_H
#include "intel_context.h"
#include "intel_ioctl.h"
#include "mtypes.h"
#include "intel_bufmgr.h"
struct intel_context;
#define BATCH_SZ 4096
#define BATCH_RESERVED 16
#define MAX_RELOCS 100
#define INTEL_BATCH_NO_CLIPRECTS 0x1
#define INTEL_BATCH_CLIPRECTS 0x2
struct buffer_reloc {
GLuint offset;
GLuint elem; /* elem in buffer list, not buffer id */
GLuint delta; /* not needed? */
};
struct intel_batchbuffer {
struct bufmgr *bm;
struct intel_context *intel;
GLuint buffer;
GLuint last_fence;
GLuint flags;
/* In progress:
*/
unsigned long offset[MAX_RELOCS];
struct _drmMMBufList *list;
GLuint list_count;
GLubyte *map;
GLubyte *ptr;
struct buffer_reloc reloc[MAX_RELOCS];
GLuint nr_relocs;
};
struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel );
void intel_batchbuffer_free( struct intel_batchbuffer *batch );
#define BATCH_LOCALS GLubyte *batch_ptr;
void intel_batchbuffer_finish( struct intel_batchbuffer *batch );
/* #define VERBOSE 0 */
#ifndef VERBOSE
extern int VERBOSE;
#endif
GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch );
#define BEGIN_BATCH(n) \
do { \
if (VERBOSE) fprintf(stderr, \
"BEGIN_BATCH(%d) in %s, %d dwords free\n", \
(n), __FUNCTION__, intel->batch.space/4); \
if (intel->batch.space < (n)*4) \
intelFlushBatch(intel, GL_TRUE); \
batch_ptr = intel->batch.ptr; \
} while (0)
/* Unlike bmBufferData, this currently requires the buffer be mapped.
* Consider it a convenience function wrapping multple
* intel_buffer_dword() calls.
*/
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
const void *data,
GLuint bytes,
GLuint flags);
#define OUT_BATCH(n) \
do { \
*(GLuint *)batch_ptr = (n); \
if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__); \
batch_ptr += 4; \
} while (0)
void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
GLuint bytes);
#define ADVANCE_BATCH() \
do { \
if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n"); \
intel->batch.space -= (batch_ptr - intel->batch.ptr); \
intel->batch.ptr = batch_ptr; \
assert(intel->batch.space >= 0); \
} while(0)
GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch,
GLuint buffer,
GLuint flags,
GLuint offset );
extern void intelInitBatchBuffer( GLcontext *ctx );
extern void intelDestroyBatchBuffer( GLcontext *ctx );
extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim );
extern void intelWrapInlinePrimitive( intelContextPtr intel );
extern void intelRestartInlinePrimitive( intelContextPtr intel );
extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
int primitive, int dwords,
int vertex_size);
extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch);
extern void intelEmitCopyBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_offset,
GLshort srcx, GLshort srcy,
GLshort dstx, GLshort dsty,
GLshort w, GLshort h );
extern void intelEmitFillBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color );
static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,
GLuint dwords )
/* Inline functions - might actually be better off with these
* non-inlined. Certainly better off switching all command packets to
* be passed as structs rather than dwords, but that's a little bit of
* work...
*/
static INLINE GLuint
intel_batchbuffer_space( struct intel_batchbuffer *batch )
{
GLuint sz = dwords * sizeof(GLuint);
GLuint *ptr;
if (intel->batch.space < sz) {
intelWrapInlinePrimitive( intel );
/* assert(intel->batch.space >= sz); */
}
/* assert(intel->prim.primitive != ~0); */
ptr = (GLuint *)intel->batch.ptr;
intel->batch.ptr += sz;
intel->batch.space -= sz;
return ptr;
return (BATCH_SZ - BATCH_RESERVED) - (batch->ptr - batch->map);
}
static INLINE void
intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch,
GLuint dword)
{
assert(batch->map);
assert(intel_batchbuffer_space(batch) >= 4);
*(GLuint *)(batch->ptr) = dword;
batch->ptr += 4;
}
static INLINE void
intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
GLuint sz,
GLuint flags)
{
assert(sz < BATCH_SZ - 8);
if (intel_batchbuffer_space(batch) < sz ||
(batch->flags != 0 && flags != 0 && batch->flags != flags))
intel_batchbuffer_flush(batch);
batch->flags |= flags;
}
/* Here are the crusty old macros, to be removed:
*/
#define BATCH_LOCALS
#define BEGIN_BATCH(n, flags) do { \
assert(!intel->prim.flush); \
intel_batchbuffer_require_space(intel->batch, (n)*4, flags); \
} while (0)
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
#define OUT_RELOC(buf,flags,delta) do { \
assert((delta) >= 0); \
intel_batchbuffer_emit_reloc(intel->batch, buf, flags, delta); \
} while (0)
#define ADVANCE_BATCH() do { } while(0)
#endif

View File

@@ -0,0 +1,444 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include <stdio.h>
#include <errno.h>
#include "mtypes.h"
#include "context.h"
#include "enums.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_buffers.h"
#include "intel_context.h"
#include "intel_fbo.h"
#include "intel_reg.h"
#include "intel_regions.h"
#include "intel_bufmgr.h"
/**
* Copy the back color buffer to the front color buffer.
* Used for SwapBuffers().
*/
void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
{
GET_CURRENT_CONTEXT(ctx);
struct intel_context *intel;
DBG("%s\n", __FUNCTION__);
assert(dPriv);
/* We need a rendering context in order to issue the blit cmd.
* Use the current context.
* XXX need to fix this someday.
*/
if (!ctx) {
_mesa_problem(NULL, "No current context in intelCopyBuffer()");
return;
}
intel = (struct intel_context *) ctx;
/* FIXME: Temporary fix for fence ageing.
*
*/
if (!intel->last_swap_fence_retired) {
bmFinishFence(intel->bm, intel->last_swap_fence);
}
/* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
* should work regardless.
*/
LOCK_HARDWARE( intel );
if (intel->driDrawable &&
intel->driDrawable->numClipRects)
{
const intelScreenPrivate *intelScreen = intel->intelScreen;
struct gl_framebuffer *fb
= (struct gl_framebuffer *) dPriv->driverPrivate;
const struct intel_region *frontRegion
= intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
const struct intel_region *backRegion
= intel_get_rb_region(fb, BUFFER_BACK_LEFT);
const int nbox = dPriv->numClipRects;
const drm_clip_rect_t *pbox = dPriv->pClipRects;
const int pitch = frontRegion->pitch;
const int cpp = frontRegion->cpp;
int BR13, CMD;
int i;
ASSERT(fb);
ASSERT(fb->Name == 0); /* Not a user-created FBO */
ASSERT(frontRegion);
ASSERT(backRegion);
ASSERT(frontRegion->pitch == backRegion->pitch);
ASSERT(frontRegion->cpp == backRegion->cpp);
if (cpp == 2) {
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
}
else {
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
}
for (i = 0 ; i < nbox; i++, pbox++)
{
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
pbox->x2 > intelScreen->width ||
pbox->y2 > intelScreen->height)
continue;
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
if (intel->sarea->pf_current_page == 0)
OUT_RELOC( frontRegion->buffer, DRM_MM_TT|DRM_MM_WRITE, 0 );
else
OUT_RELOC( backRegion->buffer, DRM_MM_TT|DRM_MM_WRITE, 0 );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( BR13 & 0xffff );
if (intel->sarea->pf_current_page == 0)
OUT_RELOC( backRegion->buffer, DRM_MM_TT|DRM_MM_READ, 0 );
else
OUT_RELOC( frontRegion->buffer, DRM_MM_TT|DRM_MM_READ, 0 );
ADVANCE_BATCH();
}
intel->last_swap_fence = intel_batchbuffer_flush( intel->batch );
intel->last_swap_fence_retired = GL_FALSE;
}
UNLOCK_HARDWARE( intel );
}
void intelEmitFillBlit( struct intel_context *intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color )
{
GLuint BR13, CMD;
BATCH_LOCALS;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
break;
default:
return;
}
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (y << 16) | x );
OUT_BATCH( ((y+h) << 16) | (x+w) );
OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset );
OUT_BATCH( color );
ADVANCE_BATCH();
}
/* Copy BitBlt
*/
void intelEmitCopyBlit( struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_buffer,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort src_x, GLshort src_y,
GLshort dst_x, GLshort dst_y,
GLshort w, GLshort h )
{
GLuint CMD, BR13;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
BATCH_LOCALS;
DBG("%s src:buf(%d)/%d+%d %d,%d dst:buf(%d)/%d+%d %d,%d sz:%dx%d\n",
__FUNCTION__,
src_buffer, src_pitch, src_offset, src_x, src_y,
dst_buffer, dst_pitch, dst_offset, dst_x, dst_y,
w,h);
src_pitch *= cpp;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = (((GLint)dst_pitch)&0xffff) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
BR13 = (((GLint)dst_pitch)&0xffff) | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
return;
}
if (dst_y2 < dst_y ||
dst_x2 < dst_x) {
return;
}
/* Initial y values don't seem to work with negative pitches. If
* we adjust the offsets manually (below), it seems to work fine.
*
* On the other hand, if we always adjust, the hardware doesn't
* know which blit directions to use, so overlapping copypixels get
* the wrong result.
*/
if ( dst_pitch > 0 &&
src_pitch > 0) {
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (dst_y << 16) | dst_x );
OUT_BATCH( (dst_y2 << 16) | dst_x2 );
OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset );
OUT_BATCH( (src_y << 16) | src_x );
OUT_BATCH( ((GLint)src_pitch&0xffff) );
OUT_RELOC( src_buffer, DRM_MM_TT|DRM_MM_READ, src_offset );
ADVANCE_BATCH();
}
else {
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (0 << 16) | dst_x );
OUT_BATCH( (h << 16) | dst_x2 );
OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset + dst_y * dst_pitch );
OUT_BATCH( (0 << 16) | src_x );
OUT_BATCH( ((GLint)src_pitch&0xffff) );
OUT_RELOC( src_buffer, DRM_MM_TT|DRM_MM_READ, src_offset + src_y * src_pitch );
ADVANCE_BATCH();
}
}
/**
* Use blitting to clear the renderbuffers named by 'flags'.
* Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferMask field
* since that might include software renderbuffers or renderbuffers
* which we're clearing with triangles.
* \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear
*/
void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
{
struct intel_context *intel = intel_context( ctx );
GLuint clear_depth;
GLbitfield skipBuffers = 0;
BATCH_LOCALS;
if (INTEL_DEBUG & DEBUG_DRI)
_mesa_printf("%s %x\n", __FUNCTION__, mask);
/*
* Compute values for clearing the buffers.
*/
clear_depth = 0;
if (mask & BUFFER_BIT_DEPTH) {
clear_depth = (GLuint) (ctx->DrawBuffer->_DepthMax * ctx->Depth.Clear);
}
if (mask & BUFFER_BIT_STENCIL) {
clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
}
/* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in
* the loop below.
*/
if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) {
skipBuffers = BUFFER_BIT_STENCIL;
}
/* XXX Move this flush/lock into the following conditional? */
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (intel->numClipRects)
{
drm_clip_rect_t clear;
int i;
if (intel->ctx.DrawBuffer->Name == 0) {
/* clearing a window */
/* flip top to bottom */
clear.x1 = cx + intel->drawX;
clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
clear.x2 = clear.x1 + cw;
clear.y2 = clear.y1 + ch;
/* adjust for page flipping */
if ( intel->sarea->pf_current_page == 1 ) {
const GLuint tmp = mask;
mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
if ( tmp & BUFFER_BIT_FRONT_LEFT ) mask |= BUFFER_BIT_BACK_LEFT;
if ( tmp & BUFFER_BIT_BACK_LEFT ) mask |= BUFFER_BIT_FRONT_LEFT;
}
}
else {
/* clearing FBO */
ASSERT(intel->numClipRects == 1);
ASSERT(intel->pClipRects == &intel->fboRect);
clear.x1 = cx;
clear.y1 = intel->ctx.DrawBuffer->Height - cy - ch;
clear.x2 = clear.y1 + cw;
clear.y2 = clear.y1 + ch;
/* no change to mask */
}
for (i = 0 ; i < intel->numClipRects ; i++)
{
const drm_clip_rect_t *box = &intel->pClipRects[i];
drm_clip_rect_t b;
GLuint buf;
GLuint clearMask = mask; /* use copy, since we modify it below */
if (!all) {
intel_intersect_cliprects(&b, &clear, box);
} else {
b = *box;
}
if (0)
_mesa_printf("clear %d,%d..%d,%d, mask %x\n",
b.x1, b.y1,
b.x2, b.y2,
mask);
/* Loop over all renderbuffers */
for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
const GLbitfield bufBit = 1 << buf;
if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
/* OK, clear this renderbuffer */
const struct intel_renderbuffer *irb
= intel_renderbuffer(ctx->DrawBuffer->
Attachment[buf].Renderbuffer);
GLuint clearVal;
GLint pitch, cpp;
GLuint BR13, CMD;
ASSERT(irb);
ASSERT(irb->region);
pitch = irb->region->pitch;
cpp = irb->region->cpp;
/* Setup the blit command */
if (cpp == 4) {
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
CMD = XY_COLOR_BLT_CMD;
if (clearMask & BUFFER_BIT_DEPTH)
CMD |= XY_COLOR_BLT_WRITE_RGB;
if (clearMask & BUFFER_BIT_STENCIL)
CMD |= XY_COLOR_BLT_WRITE_ALPHA;
}
else {
/* clearing RGBA */
CMD = (XY_COLOR_BLT_CMD |
XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
}
}
else {
ASSERT(cpp == 2 || cpp == 0);
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
CMD = XY_COLOR_BLT_CMD;
}
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
clearVal = clear_depth;
}
else {
clearVal = (cpp == 4)
? intel->ClearColor8888 : intel->ClearColor565;
}
/*
_mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
buf, irb->Base.Name);
*/
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_RELOC( irb->region->buffer, DRM_MM_TT|DRM_MM_WRITE,
irb->region->draw_offset );
OUT_BATCH( clearVal );
ADVANCE_BATCH();
clearMask &= ~bufBit; /* turn off bit, for faster loop exit */
}
}
}
intel_batchbuffer_flush( intel->batch );
}
UNLOCK_HARDWARE( intel );
}

View File

@@ -0,0 +1,60 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_BLIT_H
#define INTEL_BLIT_H
#include "intel_context.h"
#include "intel_ioctl.h"
extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch);
extern void intelEmitCopyBlit( struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_buffer,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort srcx, GLshort srcy,
GLshort dstx, GLshort dsty,
GLshort w, GLshort h );
extern void intelEmitFillBlit( struct intel_context *intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color );
#endif

View File

@@ -0,0 +1,201 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "imports.h"
#include "mtypes.h"
#include "bufferobj.h"
#include "intel_context.h"
#include "intel_buffer_objects.h"
#include "intel_bufmgr.h"
/**
* There is some duplication between mesa's bufferobjects and our
* bufmgr buffers. Both have an integer handle and a hashtable to
* lookup an opaque structure. It would be nice if the handles and
* internal structure where somehow shared.
*/
static struct gl_buffer_object *intel_bufferobj_alloc( GLcontext *ctx,
GLuint name,
GLenum target )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *obj = MALLOC_STRUCT(intel_buffer_object);
_mesa_initialize_buffer_object(&obj->Base, name, target);
/* XXX: We generate our own handle, which is different to 'name' above.
*/
bmGenBuffers(intel->bm, 1, &obj->buffer, 0);
return &obj->Base;
}
/**
* Deallocate/free a vertex/pixel buffer object.
* Called via glDeleteBuffersARB().
*/
static void intel_bufferobj_free( GLcontext *ctx,
struct gl_buffer_object *obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
if (intel_obj->buffer)
bmDeleteBuffers( intel->bm, 1, &intel_obj->buffer );
_mesa_free(intel_obj);
}
/**
* Allocate space for and store data in a buffer object. Any data that was
* previously stored in the buffer object is lost. If data is NULL,
* memory will be allocated, but no copy will occur.
* Called via glBufferDataARB().
*/
static void intel_bufferobj_data( GLcontext *ctx,
GLenum target,
GLsizeiptrARB size,
const GLvoid *data,
GLenum usage,
struct gl_buffer_object *obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
/* XXX: do something useful with 'usage' (eg. populate flags
* argument below)
*/
assert(intel_obj);
obj->Size = size;
obj->Usage = usage;
bmBufferData(intel->bm, intel_obj->buffer, size, data, 0);
}
/**
* Replace data in a subrange of buffer object. If the data range
* specified by size + offset extends beyond the end of the buffer or
* if data is NULL, no copy is performed.
* Called via glBufferSubDataARB().
*/
static void intel_bufferobj_subdata( GLcontext *ctx,
GLenum target,
GLintptrARB offset,
GLsizeiptrARB size,
const GLvoid * data,
struct gl_buffer_object * obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
bmBufferSubData(intel->bm, intel_obj->buffer, offset, size, data);
}
/**
* Called via glGetBufferSubDataARB().
*/
static void intel_bufferobj_get_subdata( GLcontext *ctx,
GLenum target,
GLintptrARB offset,
GLsizeiptrARB size,
GLvoid * data,
struct gl_buffer_object * obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
bmBufferGetSubData(intel->bm, intel_obj->buffer, offset, size, data);
}
/**
* Called via glMapBufferARB().
*/
static void *intel_bufferobj_map( GLcontext *ctx,
GLenum target,
GLenum access,
struct gl_buffer_object *obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
/* XXX: Translate access to flags arg below:
*/
assert(intel_obj);
obj->Pointer = bmMapBuffer(intel->bm, intel_obj->buffer, 0);
return obj->Pointer;
}
/**
* Called via glMapBufferARB().
*/
static GLboolean intel_bufferobj_unmap( GLcontext *ctx,
GLenum target,
struct gl_buffer_object *obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
assert(obj->Pointer);
bmUnmapBuffer(intel->bm, intel_obj->buffer);
obj->Pointer = NULL;
return GL_TRUE;
}
GLuint intel_bufferobj_buffer( const struct intel_buffer_object *intel_obj )
{
return intel_obj->buffer;
}
void intel_bufferobj_init( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
ctx->Driver.NewBufferObject = intel_bufferobj_alloc;
ctx->Driver.DeleteBuffer = intel_bufferobj_free;
ctx->Driver.BufferData = intel_bufferobj_data;
ctx->Driver.BufferSubData = intel_bufferobj_subdata;
ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata;
ctx->Driver.MapBuffer = intel_bufferobj_map;
ctx->Driver.UnmapBuffer = intel_bufferobj_unmap;
}

View File

@@ -0,0 +1,70 @@
/**************************************************************************
*
* Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_BUFFEROBJ_H
#define INTEL_BUFFEROBJ_H
#include "mtypes.h"
struct intel_context;
struct gl_buffer_object;
/**
* Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object.
*/
struct intel_buffer_object {
struct gl_buffer_object Base;
GLuint buffer; /* the low-level buffer manager's buffer handle */
};
/* Get the bm buffer associated with a GL bufferobject:
*/
GLuint intel_bufferobj_buffer( const struct intel_buffer_object *obj );
/* Hook the bufferobject implementation into mesa:
*/
void intel_bufferobj_init( struct intel_context *intel );
/* Are the obj->Name tests necessary? Unfortunately yes, mesa
* allocates a couple of gl_buffer_object structs statically, and
* the Name == 0 test is the only way to identify them and avoid
* casting them erroneously to our structs.
*/
static INLINE struct intel_buffer_object *
intel_buffer_object( struct gl_buffer_object *obj )
{
if (obj->Name)
return (struct intel_buffer_object *)obj;
else
return NULL;
}
#endif

View File

@@ -0,0 +1,730 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_blit.h"
#include "intel_buffers.h"
#include "intel_depthstencil.h"
#include "intel_fbo.h"
#include "intel_tris.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
#include "context.h"
#include "framebuffer.h"
#include "swrast/swrast.h"
/**
* XXX move this into a new dri/common/cliprects.c file.
*/
GLboolean intel_intersect_cliprects( drm_clip_rect_t *dst,
const drm_clip_rect_t *a,
const drm_clip_rect_t *b )
{
GLint bx = b->x1;
GLint by = b->y1;
GLint bw = b->x2 - bx;
GLint bh = b->y2 - by;
if (bx < a->x1) bw -= a->x1 - bx, bx = a->x1;
if (by < a->y1) bh -= a->y1 - by, by = a->y1;
if (bx + bw > a->x2) bw = a->x2 - bx;
if (by + bh > a->y2) bh = a->y2 - by;
if (bw <= 0) return GL_FALSE;
if (bh <= 0) return GL_FALSE;
dst->x1 = bx;
dst->y1 = by;
dst->x2 = bx + bw;
dst->y2 = by + bh;
return GL_TRUE;
}
/**
* Return pointer to current color drawing region, or NULL.
*/
struct intel_region *intel_drawbuf_region( struct intel_context *intel )
{
struct intel_renderbuffer *irbColor =
intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]);
if (irbColor)
return irbColor->region;
else
return NULL;
}
/**
* Return pointer to current color reading region, or NULL.
*/
struct intel_region *intel_readbuf_region( struct intel_context *intel )
{
struct intel_renderbuffer *irb
= intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
if (irb)
return irb->region;
else
return NULL;
}
static void intelBufferSize(GLframebuffer *buffer,
GLuint *width,
GLuint *height)
{
GET_CURRENT_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
/* Need to lock to make sure the driDrawable is uptodate. This
* information is used to resize Mesa's software buffers, so it has
* to be correct.
*/
/* XXX This isn't 100% correct, the given buffer might not be
* bound to the current context!
*/
LOCK_HARDWARE(intel);
if (intel->driDrawable) {
*width = intel->driDrawable->w;
*height = intel->driDrawable->h;
}
else {
*width = 0;
*height = 0;
}
UNLOCK_HARDWARE(intel);
}
/**
* Update the following fields for rendering to a user-created FBO:
* intel->numClipRects
* intel->pClipRects
* intel->drawX
* intel->drawY
*/
static void intelSetRenderbufferClipRects( struct intel_context *intel )
{
assert(intel->ctx.DrawBuffer->Width > 0);
assert(intel->ctx.DrawBuffer->Height > 0);
intel->fboRect.x1 = 0;
intel->fboRect.y1 = 0;
intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
intel->numClipRects = 1;
intel->pClipRects = &intel->fboRect;
intel->drawX = 0;
intel->drawY = 0;
}
/**
* As above, but for rendering to front buffer of a window.
* \sa intelSetRenderbufferClipRects
*/
static void intelSetFrontClipRects( struct intel_context *intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
}
/**
* As above, but for rendering to back buffer of a window.
*/
static void intelSetBackClipRects( struct intel_context *intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
/* use the front clip rects */
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
} else {
/* use the back clip rects */
intel->numClipRects = dPriv->numBackClipRects;
intel->pClipRects = dPriv->pBackClipRects;
intel->drawX = dPriv->backX;
intel->drawY = dPriv->backY;
if (dPriv->numBackClipRects == 1 &&
dPriv->x == dPriv->backX &&
dPriv->y == dPriv->backY) {
/* Repeat the calculation of the back cliprect dimensions here
* as early versions of dri.a in the Xserver are incorrect. Try
* very hard not to restrict future versions of dri.a which
* might eg. allocate truly private back buffers.
*/
int x1, y1;
int x2, y2;
x1 = dPriv->x;
y1 = dPriv->y;
x2 = dPriv->x + dPriv->w;
y2 = dPriv->y + dPriv->h;
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
if (x1 == dPriv->pBackClipRects[0].x1 &&
y1 == dPriv->pBackClipRects[0].y1) {
dPriv->pBackClipRects[0].x2 = x2;
dPriv->pBackClipRects[0].y2 = y2;
}
}
}
}
/**
* This will be called whenever the currently bound window is moved/resized.
* XXX: actually, it seems to NOT be called when the window is only moved (BP).
*/
void intelWindowMoved( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
if (!intel->ctx.DrawBuffer) {
/* when would this happen? -BP */
intelSetFrontClipRects( intel );
}
else if (intel->ctx.DrawBuffer->Name != 0) {
/* drawing to user-created FBO - do nothing */
/* Cliprects would be set from intelDrawBuffer() */
}
else {
/* drawing to a window */
switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
case BUFFER_BIT_FRONT_LEFT:
intelSetFrontClipRects( intel );
break;
case BUFFER_BIT_BACK_LEFT:
intelSetBackClipRects( intel );
break;
default:
/* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
intelSetFrontClipRects( intel );
}
}
/* this update Mesa's notion of window size */
if (ctx->WinSysDrawBuffer) {
_mesa_resize_framebuffer(ctx, ctx->WinSysDrawBuffer,
intel->driDrawable->w, intel->driDrawable->h);
}
/* Update hardware scissor */
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
}
/* A true meta version of this would be very simple and additionally
* machine independent. Maybe we'll get there one day.
*/
static void intelClearWithTris(struct intel_context *intel,
GLbitfield mask,
GLboolean all,
GLint cx, GLint cy,
GLint cw, GLint ch)
{
GLcontext *ctx = &intel->ctx;
drm_clip_rect_t clear;
if (INTEL_DEBUG & DEBUG_DRI)
_mesa_printf("%s 0x%x\n", __FUNCTION__, mask);
LOCK_HARDWARE(intel);
/* XXX FBO: was: intel->driDrawable->numClipRects */
if (intel->numClipRects) {
GLuint buf;
intel->vtbl.install_meta_state(intel);
/* note: regardless of 'all', cx, cy, cw, ch are correct */
clear.x1 = cx;
clear.y1 = cy;
clear.x2 = cx + cw;
clear.y2 = cy + ch;
/* Back and stencil cliprects are the same. Try and do both
* buffers at once:
*/
if (mask & (BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH)) {
struct intel_region *backRegion
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT);
struct intel_region *depthRegion
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH);
const GLuint clearColor = (backRegion && backRegion->cpp == 4)
? intel->ClearColor8888 : intel->ClearColor565;
intel->vtbl.meta_draw_region(intel, backRegion, depthRegion );
if (mask & BUFFER_BIT_BACK_LEFT)
intel->vtbl.meta_color_mask(intel, GL_TRUE );
else
intel->vtbl.meta_color_mask(intel, GL_FALSE );
if (mask & BUFFER_BIT_STENCIL)
intel->vtbl.meta_stencil_replace( intel,
intel->ctx.Stencil.WriteMask[0],
intel->ctx.Stencil.Clear);
else
intel->vtbl.meta_no_stencil_write(intel);
if (mask & BUFFER_BIT_DEPTH)
intel->vtbl.meta_depth_replace( intel );
else
intel->vtbl.meta_no_depth_write(intel);
/* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
* drawing origin may not be correctly emitted.
*/
intel_meta_draw_quad(intel,
clear.x1, clear.x2,
clear.y1, clear.y2,
intel->ctx.Depth.Clear,
clearColor,
0, 0, 0, 0); /* texcoords */
mask &= ~(BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH);
}
/* clear the remaining (color) renderbuffers */
for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
const GLuint bufBit = 1 << buf;
if (mask & bufBit) {
struct intel_renderbuffer *irbColor =
intel_renderbuffer(ctx->DrawBuffer->
Attachment[buf].Renderbuffer);
GLuint color = (irbColor->region->cpp == 4)
? intel->ClearColor8888 : intel->ClearColor565;
ASSERT(irbColor);
intel->vtbl.meta_no_depth_write(intel);
intel->vtbl.meta_no_stencil_write(intel);
intel->vtbl.meta_color_mask(intel, GL_TRUE );
intel->vtbl.meta_draw_region(intel, irbColor->region, NULL);
/* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
* drawing origin may not be correctly emitted.
*/
intel_meta_draw_quad(intel,
clear.x1, clear.x2,
clear.y1, clear.y2,
0, /* depth clear val */
color,
0, 0, 0, 0); /* texcoords */
mask &= ~bufBit;
}
}
intel->vtbl.leave_meta_state( intel );
intel_batchbuffer_flush( intel->batch );
}
UNLOCK_HARDWARE(intel);
}
/**
* Called by ctx->Driver.Clear.
*/
static void intelClear(GLcontext *ctx,
GLbitfield mask,
GLboolean all,
GLint cx, GLint cy,
GLint cw, GLint ch)
{
struct intel_context *intel = intel_context( ctx );
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
GLbitfield tri_mask = 0;
GLbitfield blit_mask = 0;
GLbitfield swrast_mask = 0;
GLuint i;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
/* HW color buffers (front, back, aux, generic FBO, etc) */
if (colorMask == ~0) {
/* clear all R,G,B,A */
/* XXX FBO: need to check if colorbuffers are software RBOs! */
blit_mask |= (mask & BUFFER_BITS_COLOR);
}
else {
/* glColorMask in effect */
tri_mask |= (mask & BUFFER_BITS_COLOR);
}
/* HW stencil */
if (mask & BUFFER_BIT_STENCIL) {
const struct intel_region *stencilRegion
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL);
if (stencilRegion) {
/* have hw stencil */
if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
/* not clearing all stencil bits, so use triangle clearing */
tri_mask |= BUFFER_BIT_STENCIL;
}
else {
/* clearing all stencil bits, use blitting */
blit_mask |= BUFFER_BIT_STENCIL;
}
}
}
/* HW depth */
if (mask & BUFFER_BIT_DEPTH) {
/* clear depth with whatever method is used for stencil (see above) */
if (tri_mask & BUFFER_BIT_STENCIL)
tri_mask |= BUFFER_BIT_DEPTH;
else
blit_mask |= BUFFER_BIT_DEPTH;
}
/* SW fallback clearing */
swrast_mask = mask & ~tri_mask & ~blit_mask;
for (i = 0; i < BUFFER_COUNT; i++) {
GLuint bufBit = 1 << i;
if ((blit_mask | tri_mask) & bufBit) {
if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) {
blit_mask &= ~bufBit;
tri_mask &= ~bufBit;
swrast_mask |= bufBit;
}
}
}
intelFlush( ctx ); /* XXX intelClearWithBlit also does this */
if (blit_mask)
intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
if (tri_mask)
intelClearWithTris( intel, tri_mask, all, cx, cy, cw, ch);
if (swrast_mask)
_swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
}
/* Flip the front & back buffers
*/
static void intelPageFlip( const __DRIdrawablePrivate *dPriv )
{
#if 0
struct intel_context *intel;
int tmp, ret;
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (dPriv->pClipRects) {
*(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
intel->sarea->nbox = 1;
}
ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
if (ret) {
fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
UNLOCK_HARDWARE( intel );
exit(1);
}
tmp = intel->sarea->last_enqueue;
intelRefillBatchLocked( intel );
UNLOCK_HARDWARE( intel );
intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
#endif
}
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driverPrivate) {
const struct gl_framebuffer *fb
= (struct gl_framebuffer *) dPriv->driverPrivate;
if (fb->Visual.doubleBufferMode) {
GET_CURRENT_CONTEXT(ctx);
if (ctx && ctx->DrawBuffer == fb) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering */
}
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
intelPageFlip( dPriv );
} else {
intelCopyBuffer( dPriv );
}
}
}
else {
_mesa_problem(NULL,
"dPriv has no gl_framebuffer pointer in intelSwapBuffers");
}
}
/**
* Update the hardware state for drawing into a window or framebuffer object.
*
* Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
* places within the driver.
*
* Basically, this needs to be called any time the current framebuffer
* changes, the renderbuffers change, or we need to draw into different
* color buffers.
*/
void
intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
{
struct intel_context *intel = intel_context(ctx);
struct intel_region *colorRegion, *depthRegion = NULL;
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
int front = 0; /* drawing to front color buffer? */
if (!fb) {
/* this can happen during the initial context initialization */
return;
}
/* Do this here, note core Mesa, since this function is called from
* many places within the driver.
*/
if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
/* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
_mesa_update_framebuffer(ctx);
/* this updates the DrawBuffer's Width/Height if it's a FBO */
_mesa_update_draw_buffer_bounds(ctx);
}
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
/* this may occur when we're called by glBindFrameBuffer() during
* the process of someone setting up renderbuffers, etc.
*/
_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");
return;
}
if (fb->Name)
intel_validate_paired_depth_stencil(ctx, fb);
/*
* How many color buffers are we drawing into?
*/
if (fb->_NumColorDrawBuffers[0] != 1
#if 0
/* XXX FBO temporary - always use software rendering */
|| 1
#endif
) {
/* writing to 0 or 2 or 4 color buffers */
/*_mesa_debug(ctx, "Software rendering\n");*/
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
front = 1; /* might not have back color buffer */
}
else {
/* draw to exactly one color buffer */
/*_mesa_debug(ctx, "Hardware rendering\n");*/
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
front = 1;
}
}
/*
* Get the intel_renderbuffer for the colorbuffer we're drawing into.
* And set up cliprects.
*/
if (fb->Name == 0) {
/* drawing to window system buffer */
if (intel->sarea->pf_current_page == 1 ) {
/* page flipped back/front */
front ^= 1;
}
if (front) {
intelSetFrontClipRects( intel );
colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
}
else {
intelSetBackClipRects( intel );
colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
}
}
else {
/* drawing to user-created FBO */
struct intel_renderbuffer *irb;
intelSetRenderbufferClipRects(intel);
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
colorRegion = (irb && irb->region) ? irb->region : NULL;
}
if (!colorRegion) {
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
}
else {
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
}
/***
*** Get depth buffer region and check if we need a software fallback.
*** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
***/
if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
if (irbDepth->region) {
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
depthRegion = irbDepth->region;
}
else {
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
depthRegion = NULL;
}
}
else {
/* not using depth buffer */
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
depthRegion = NULL;
}
/***
*** Stencil buffer
*** This can only be hardware accelerated if we're using a
*** combined DEPTH_STENCIL buffer (for now anyway).
***/
if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
if (irbStencil && irbStencil->region) {
ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
/* need to re-compute stencil hw state */
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
if (!depthRegion)
depthRegion = irbStencil->region;
}
else {
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
}
}
else {
/* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
/* need to re-compute stencil hw state */
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
}
/**
** Release old regions, reference new regions
**/
#if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
if (intel->draw_region != colorRegion) {
intel_region_release(intel, &intel->draw_region);
intel_region_reference(&intel->draw_region, colorRegion);
}
if (intel->depth_region != depthRegion) {
intel_region_release(intel, &intel->depth_region);
intel_region_reference(&intel->depth_region, depthRegion);
}
#endif
intel->vtbl.set_draw_region( intel, colorRegion, depthRegion );
/* update viewport since it depends on window size */
ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
ctx->Viewport.Width, ctx->Viewport.Height);
/* Update hardware scissor */
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
}
static void
intelDrawBuffer(GLcontext *ctx, GLenum mode)
{
intel_draw_buffer(ctx, ctx->DrawBuffer);
}
static void
intelReadBuffer( GLcontext *ctx, GLenum mode )
{
if (ctx->ReadBuffer == ctx->DrawBuffer) {
/* This will update FBO completeness status.
* A framebuffer will be incomplete if the GL_READ_BUFFER setting
* refers to a missing renderbuffer. Calling glReadBuffer can set
* that straight and can make the drawing buffer complete.
*/
intel_draw_buffer(ctx, ctx->DrawBuffer);
}
/* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
* reference ctx->ReadBuffer and do appropriate state checks.
*/
}
void intelInitBufferFuncs( struct dd_function_table *functions )
{
functions->Clear = intelClear;
functions->GetBufferSize = intelBufferSize;
functions->ResizeBuffers = _mesa_resize_framebuffer;
functions->DrawBuffer = intelDrawBuffer;
functions->ReadBuffer = intelReadBuffer;
}

View File

@@ -0,0 +1,58 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_BUFFERS_H
#define INTEL_BUFFERS_H
struct intel_context;
extern GLboolean
intel_intersect_cliprects(drm_clip_rect_t *dest,
const drm_clip_rect_t *a,
const drm_clip_rect_t *b);
extern struct intel_region *
intel_readbuf_region(struct intel_context *intel);
extern struct intel_region *
intel_drawbuf_region(struct intel_context *intel);
extern void
intelSwapBuffers( __DRIdrawablePrivate *dPriv);
extern void
intelWindowMoved(struct intel_context *intel);
extern void
intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb);
extern void
intelInitBufferFuncs(struct dd_function_table *functions);
#endif /* INTEL_BUFFERS_H */

View File

@@ -0,0 +1,453 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
#include "intel_bufmgr.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "hash.h"
#include "simple_list.h"
#include "mm.h"
#include "imports.h"
#include "glthread.h"
#include <sys/ioctl.h>
#include <unistd.h>
#include <drm.h>
struct _mesa_HashTable;
/* The buffer manager is really part of the gl_shared_state struct.
* TODO: Organize for the bufmgr to be created/deleted with the shared
* state and stored within the DriverData of that struct. Currently
* there are no mesa callbacks for this.
*/
#define BM_MAX 16
static struct bufmgr
{
_glthread_Mutex mutex; /**< for thread safety */
int driFd;
int refcount;
struct _mesa_HashTable *hash;
unsigned buf_nr; /* for generating ids */
drmMMPool batchPool;
drmFence initFence;
} bufmgr_pool[BM_MAX];
static int nr_bms;
#define LOCK(bm) _glthread_LOCK_MUTEX(bm->mutex)
#define UNLOCK(bm) _glthread_UNLOCK_MUTEX(bm->mutex)
static void
bmError(int val, const char *file, const char *function, int line)
{
_mesa_printf("Fatal video memory manager error \"%s\".\n"
"Check kernel logs or set the LIBGL_DEBUG\n"
"environment variable to \"verbose\" for more info.\n"
"Detected in file %s, line %d, function %s.\n",
strerror(-val), file, line, function);
#ifndef NDEBUG
exit(-1);
#else
abort();
#endif
}
#define BM_CKFATAL(val) \
do{ \
int tstVal = (val); \
if (tstVal) \
bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \
} while(0);
/***********************************************************************
* Public functions
*/
/* The initialization functions are skewed in the fake implementation.
* This call would be to attach to an existing manager, rather than to
* create a local one.
*/
struct bufmgr *
bm_intel_Attach(struct intel_context *intel)
{
GLuint i;
for (i = 0; i < nr_bms; i++)
if (bufmgr_pool[i].driFd == intel->driFd) {
bufmgr_pool[i].refcount++;
_mesa_printf("retrieive old bufmgr for fd %d\n",
bufmgr_pool[i].driFd);
return &bufmgr_pool[i];
}
if (nr_bms < BM_MAX) {
struct bufmgr *bm = &bufmgr_pool[nr_bms++];
_mesa_printf("create new bufmgr for fd %d\n", intel->driFd);
bm->driFd = intel->driFd;
bm->hash = _mesa_NewHashTable();
bm->refcount = 1;
_glthread_INIT_MUTEX(bm->mutex);
drmGetLock(bm->driFd, intel->hHWContext, 0);
BM_CKFATAL(drmMMAllocBufferPool(bm->driFd, mmPoolRing, 0,
DRM_MM_TT | DRM_MM_NO_EVICT |
DRM_MM_READ | DRM_MM_EXE |
BM_BATCHBUFFER, 1024 * 1024, 4096,
&bm->batchPool));
BM_CKFATAL(drmEmitFence(bm->driFd, 0, &bm->initFence));
drmUnlock(bm->driFd, intel->hHWContext);
return bm;
}
_mesa_printf("failed to create new bufmgr for fd %d\n", intel->driFd);
return NULL;
}
void
bmGenBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers, unsigned flags)
{
LOCK(bm);
{
unsigned i;
unsigned bFlags =
(flags) ? flags : DRM_MM_TT | DRM_MM_VRAM | DRM_MM_SYSTEM;
for (i = 0; i < n; i++) {
drmMMBuf *buf = calloc(sizeof(*buf), 1);
BM_CKFATAL(drmMMInitBuffer(bm->driFd, bFlags, 12, buf));
buf->client_priv = ++bm->buf_nr;
buffers[i] = buf->client_priv;
_mesa_HashInsert(bm->hash, buffers[i], buf);
}
}
UNLOCK(bm);
}
void
bmSetShared(struct bufmgr *bm, unsigned buffer, unsigned flags,
unsigned long offset, void *virtual)
{
LOCK(bm);
{
drmMMBuf *buf = _mesa_HashLookup(bm->hash, buffer);
assert(buf);
buf->flags = DRM_MM_NO_EVICT | DRM_MM_SHARED
| DRM_MM_WRITE | DRM_MM_READ;
buf->flags |= flags & DRM_MM_MEMTYPE_MASK;
buf->offset = offset;
buf->virtual = virtual;
BM_CKFATAL(drmMMAllocBuffer(bm->driFd, 0, NULL, 0, buf));
}
UNLOCK(bm);
}
void
bmDeleteBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers)
{
LOCK(bm);
{
unsigned i;
for (i = 0; i < n; i++) {
drmMMBuf *buf = _mesa_HashLookup(bm->hash, buffers[i]);
if (buf) {
BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));
_mesa_HashRemove(bm->hash, buffers[i]);
}
}
}
UNLOCK(bm);
}
/* If buffer size changes, free and reallocate. Otherwise update in
* place.
*/
void
bmBufferData(struct bufmgr *bm,
unsigned buffer, unsigned size, const void *data, unsigned flags)
{
LOCK(bm);
{
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
DBG("bmBufferData %d sz 0x%x data: %p\n", buffer, size, data);
assert(buf);
assert(!buf->mapped);
if (buf->flags & BM_BATCHBUFFER) {
BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));
BM_CKFATAL(drmMMAllocBuffer
(bm->driFd, size, &bm->batchPool, 1, buf));
} else if (!(buf->flags & DRM_MM_SHARED)) {
if (buf->block && (buf->size < size || drmBufIsBusy(bm->driFd, buf))) {
BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));
}
if (!buf->block) {
BM_CKFATAL(drmMMAllocBuffer(bm->driFd, size, NULL, 0, buf));
}
}
if (data != NULL) {
memcpy(drmMMMapBuffer(bm->driFd, buf), data, size);
drmMMUnmapBuffer(bm->driFd, buf);
}
}
UNLOCK(bm);
}
/* Update the buffer in place, in whatever space it is currently resident:
*/
void
bmBufferSubData(struct bufmgr *bm,
unsigned buffer,
unsigned offset, unsigned size, const void *data)
{
LOCK(bm);
{
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);
assert(buf);
drmBufWaitBusy(bm->driFd, buf);
if (size) {
memcpy((unsigned char *) drmMMMapBuffer(bm->driFd, buf) + offset,
data, size);
drmMMUnmapBuffer(bm->driFd, buf);
}
}
UNLOCK(bm);
}
/* Extract data from the buffer:
*/
void
bmBufferGetSubData(struct bufmgr *bm,
unsigned buffer,
unsigned offset, unsigned size, void *data)
{
LOCK(bm);
{
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);
assert(buf);
drmBufWaitBusy(bm->driFd, buf);
if (size) {
memcpy(data,
(unsigned char *) drmMMMapBuffer(bm->driFd, buf) + offset,
size);
drmMMUnmapBuffer(bm->driFd, buf);
}
}
UNLOCK(bm);
}
/* Return a pointer to whatever space the buffer is currently resident in:
*/
void *
bmMapBuffer(struct bufmgr *bm, unsigned buffer, unsigned flags)
{
void *retval;
LOCK(bm);
{
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
DBG("bmMapBuffer %d\n", buffer);
DBG("Map: Block is 0x%x\n", &buf->block);
assert(buf);
/* assert(!buf->mapped); */
retval = drmMMMapBuffer(bm->driFd, buf);
}
UNLOCK(bm);
return retval;
}
void
bmUnmapBuffer(struct bufmgr *bm, unsigned buffer)
{
LOCK(bm);
{
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
if (!buf)
goto out;
DBG("bmUnmapBuffer %d\n", buffer);
drmMMUnmapBuffer(bm->driFd, buf);
}
out:
UNLOCK(bm);
}
/* Build the list of buffers to validate. Note that the buffer list
* isn't a shared structure so we don't need mutexes when manipulating
* it.
*
* XXX: need refcounting for drmMMBuf structs so that they can't be
* deleted while on these lists.
*/
struct _drmMMBufList *
bmNewBufferList(void)
{
return drmMMInitListHead();
}
int
bmAddBuffer(struct bufmgr *bm,
struct _drmMMBufList *list,
unsigned buffer,
unsigned flags,
unsigned *memtype_return, unsigned long *offset_return)
{
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
assert(buf);
return drmMMBufListAdd(list, buf, 0, flags, memtype_return, offset_return);
}
void
bmFreeBufferList(struct _drmMMBufList *list)
{
drmMMFreeBufList(list);
}
int
bmScanBufferList(struct bufmgr *bm,
struct _drmMMBufList *list, unsigned buffer)
{
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
assert(buf);
return drmMMScanBufList(list, buf);
}
/* To be called prior to emitting commands to hardware which reference
* these buffers. The buffer_usage list provides information on where
* the buffers should be placed and whether their contents need to be
* preserved on copying. The offset and pool data elements are return
* values from this function telling the driver exactly where the
* buffers are currently located.
*/
int
bmValidateBufferList(struct bufmgr *bm,
struct _drmMMBufList *list, unsigned flags)
{
BM_CKFATAL(drmMMValidateBuffers(bm->driFd, list));
return 0;
}
/* After commands are emitted but before unlocking, this must be
* called so that the buffer manager can correctly age the buffers.
* The buffer manager keeps track of the list of validated buffers, so
* already knows what to apply the fence to.
*
* The buffer manager knows how to emit and test fences directly
* through the drm and without callbacks or whatever into the driver.
*/
unsigned
bmFenceBufferList(struct bufmgr *bm, struct _drmMMBufList *list)
{
drmFence fence;
BM_CKFATAL(drmMMFenceBuffers(bm->driFd, list));
BM_CKFATAL(drmEmitFence(bm->driFd, 0, &fence));
return fence.fenceSeq;
}
/* This functionality is used by the buffer manager, not really sure
* if we need to be exposing it in this way, probably libdrm will
* offer equivalent calls.
*
* For now they can stay, but will likely change/move before final:
*/
unsigned
bmSetFence(struct bufmgr *bm)
{
drmFence dFence;
BM_CKFATAL(drmEmitFence(bm->driFd, 0, &dFence));
return dFence.fenceSeq;
}
int
bmTestFence(struct bufmgr *bm, unsigned fence)
{
drmFence dFence;
int retired;
dFence.fenceType = 0;
dFence.fenceSeq = fence;
BM_CKFATAL(drmTestFence(bm->driFd, dFence, 0, &retired));
return retired;
}
void
bmFinishFence(struct bufmgr *bm, unsigned fence)
{
drmFence dFence;
dFence.fenceType = 0;
dFence.fenceSeq = fence;
BM_CKFATAL(drmWaitFence(bm->driFd, dFence));
bm->initFence = dFence;
}
unsigned
bmInitFence(struct bufmgr *bm)
{
return bm->initFence.fenceSeq;
}

View File

@@ -0,0 +1,132 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
#ifndef BUFMGR_H
#define BUFMGR_H
#include "intel_context.h"
/* Note that this is destined to be external to Mesa, so don't use GL
* types like GLuint, etc.
*/
/* The buffer manager context. Opaque.
*/
struct bufmgr;
struct bufmgr *bm_intel_Attach(struct intel_context *intel);
#define BM_BATCHBUFFER 0x10000000 /* for map - pointer will be accessed
* without dri lock */
/* Stick closely to ARB_vbo semantics - they're well defined and
* understood, and drivers can just pass the calls through without too
* much thunking.
*/
void bmGenBuffers(struct bufmgr *, unsigned n, unsigned *buffers,
unsigned flags);
void bmDeleteBuffers(struct bufmgr *, unsigned n, unsigned *buffers);
/* The driver has more intimate knowledge of the hardare than a GL
* client would, so flags here is more proscriptive than the usage
* values in the ARB_vbo interface:
*/
void bmBufferData(struct bufmgr *,
unsigned buffer,
unsigned size, const void *data, unsigned flags);
void bmBufferSubData(struct bufmgr *,
unsigned buffer,
unsigned offset, unsigned size, const void *data);
void bmBufferGetSubData(struct bufmgr *,
unsigned buffer,
unsigned offset, unsigned size, void *data);
void *bmMapBuffer(struct bufmgr *, unsigned buffer, unsigned access);
void bmUnmapBuffer(struct bufmgr *, unsigned buffer);
/* To be called prior to emitting commands to hardware which reference
* these buffers.
*
* NewBufferList() and AddBuffer() build up a list of buffers to be
* validated. The buffer list provides information on where the
* buffers should be placed and whether their contents need to be
* preserved on copying. The offset data elements are return values
* from this function telling the driver exactly where the buffers are
* currently located.
*
* ValidateBufferList() performs the actual validation and returns the
* buffer pools and offsets within the pools.
*
* FenceBufferList() must be called to set fences and other
* housekeeping before unlocking after a successful call to
* ValidateBufferList(). The buffer manager knows how to emit and test
* fences directly through the drm and without callbacks to the
* driver.
*/
struct _drmMMBufList *bmNewBufferList(void);
int bmAddBuffer(struct bufmgr *bm,
struct _drmMMBufList *list,
unsigned buffer,
unsigned flags,
unsigned *pool_return, unsigned long *offset_return);
int bmValidateBufferList(struct bufmgr *,
struct _drmMMBufList *, unsigned flags);
unsigned bmFenceBufferList(struct bufmgr *, struct _drmMMBufList *);
void bmFreeBufferList(struct _drmMMBufList *);
int bmScanBufferList(struct bufmgr *bm,
struct _drmMMBufList *list, unsigned buffer);
/* This functionality is used by the buffer manager, not really sure
* if we need to be exposing it in this way, probably libdrm will
* offer equivalent calls.
*
* For now they can stay, but will likely change/move before final:
*/
unsigned bmSetFence(struct bufmgr *);
int bmTestFence(struct bufmgr *, unsigned fence);
void bmFinishFence(struct bufmgr *, unsigned fence);
unsigned bmInitFence(struct bufmgr *bm);
void bmSetShared(struct bufmgr *bm, unsigned buffer,
unsigned flags, unsigned long offset, void *virtual);
extern int INTEL_DEBUG;
#define DEBUG_BUFMGR 0x2000
#define DBG(...) do { if (INTEL_DEBUG & DEBUG_BUFMGR) _mesa_printf(__VA_ARGS__); } while(0)
#endif

View File

@@ -47,13 +47,20 @@
#include "intel_screen.h"
#include "i830_dri.h"
#include "i830_common.h"
#include "intel_buffers.h"
#include "intel_tex.h"
#include "intel_span.h"
#include "intel_tris.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_pixel.h"
#include "intel_regions.h"
#include "intel_buffer_objects.h"
#include "intel_fbo.h"
#include "intel_bufmgr.h"
#include "utils.h"
#ifndef INTEL_DEBUG
@@ -72,27 +79,20 @@ int INTEL_DEBUG = (0);
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_cull_vertex
#define need_GL_EXT_fog_coord
#define need_GL_EXT_framebuffer_object
#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_secondary_color
#define need_GL_NV_vertex_program
#include "extension_helper.h"
#ifndef VERBOSE
int VERBOSE = 0;
#endif
#if DEBUG_LOCKING
char *prevLockFile;
int prevLockLine;
#endif
#define DRIVER_DATE "20060329"
/***************************************
* Mesa's Driver Functions
***************************************/
_glthread_Mutex lockMutex;
static GLboolean lockMutexInit = GL_FALSE;
#define DRIVER_DATE "20050225"
const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
static const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
{
const char * chipset;
static char buffer[128];
@@ -103,7 +103,7 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
break;
case GL_RENDERER:
switch (INTEL_CONTEXT(ctx)->intelScreen->deviceID) {
switch (intel_context(ctx)->intelScreen->deviceID) {
case PCI_CHIP_845_G:
chipset = "Intel(R) 845G"; break;
case PCI_CHIP_I830_M:
@@ -130,27 +130,6 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
}
}
static void intelBufferSize(GLframebuffer *buffer,
GLuint *width, GLuint *height)
{
GET_CURRENT_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
/* Need to lock to make sure the driDrawable is uptodate. This
* information is used to resize Mesa's software buffers, so it has
* to be correct.
*/
LOCK_HARDWARE(intel);
if (intel->driDrawable) {
*width = intel->driDrawable->w;
*height = intel->driDrawable->h;
}
else {
*width = 0;
*height = 0;
}
UNLOCK_HARDWARE(intel);
}
/**
* Extension strings exported by the intel driver.
@@ -173,6 +152,7 @@ const struct dri_extension card_extensions[] =
{ "GL_ARB_texture_mirrored_repeat", NULL },
{ "GL_ARB_texture_rectangle", NULL },
{ "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_ARB_pixel_buffer_object", NULL },
{ "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
{ "GL_ARB_window_pos", GL_ARB_window_pos_functions },
{ "GL_EXT_blend_color", GL_EXT_blend_color_functions },
@@ -182,7 +162,11 @@ const struct dri_extension card_extensions[] =
{ "GL_EXT_blend_subtract", NULL },
{ "GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
{ "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
{ "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
#if 1 /* XXX FBO temporary? */
{ "GL_EXT_packed_depth_stencil", NULL },
#endif
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
{ "GL_EXT_stencil_wrap", NULL },
{ "GL_EXT_texture_edge_clamp", NULL },
@@ -197,7 +181,7 @@ const struct dri_extension card_extensions[] =
{ "GL_NV_blend_square", NULL },
{ "GL_NV_vertex_program", GL_NV_vertex_program_functions },
{ "GL_NV_vertex_program1_1", NULL },
{ "GL_SGIS_generate_mipmap", NULL },
/* { "GL_SGIS_generate_mipmap", NULL }, */
{ NULL, NULL }
};
@@ -237,6 +221,7 @@ static const struct dri_debug_control debug_control[] =
{ "sync", DEBUG_SYNC },
{ "sleep", DEBUG_SLEEP },
{ "pix", DEBUG_PIXEL },
{ "buf", DEBUG_BUFMGR },
{ NULL, 0 }
};
@@ -248,7 +233,32 @@ static void intelInvalidateState( GLcontext *ctx, GLuint new_state )
_ac_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
_tnl_invalidate_vertex_state( ctx, new_state );
INTEL_CONTEXT(ctx)->NewGLState |= new_state;
intel_context(ctx)->NewGLState |= new_state;
}
void intelFlush( GLcontext *ctx )
{
struct intel_context *intel = intel_context( ctx );
if (intel->Fallback)
_swrast_flush( ctx );
INTEL_FIREVERTICES( intel );
if (intel->batch->map != intel->batch->ptr)
intel_batchbuffer_flush( intel->batch );
/* XXX: Need to do an MI_FLUSH here. Actually, the bufmgr_fake.c
* code will have done one already.
*/
}
void intelFinish( GLcontext *ctx )
{
struct intel_context *intel = intel_context( ctx );
intelFlush( ctx );
bmFinishFence( intel->bm, intel->batch->last_fence );
}
@@ -257,10 +267,7 @@ void intelInitDriverFunctions( struct dd_function_table *functions )
_mesa_init_driver_functions( functions );
functions->Flush = intelFlush;
functions->Clear = intelClear;
functions->Finish = intelFinish;
functions->GetBufferSize = intelBufferSize;
functions->ResizeBuffers = _mesa_resize_framebuffer;
functions->GetString = intelGetString;
functions->UpdateState = intelInvalidateState;
functions->CopyColorTable = _swrast_CopyColorTable;
@@ -271,11 +278,12 @@ void intelInitDriverFunctions( struct dd_function_table *functions )
intelInitTextureFuncs( functions );
intelInitPixelFuncs( functions );
intelInitStateFuncs( functions );
intelInitBufferFuncs( functions );
}
GLboolean intelInitContext( intelContextPtr intel,
GLboolean intelInitContext( struct intel_context *intel,
const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate,
@@ -299,9 +307,10 @@ GLboolean intelInitContext( intelContextPtr intel,
intel->driScreen = sPriv;
intel->sarea = saPriv;
(void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) );
make_empty_list( & intel->swapped );
if (!lockMutexInit) {
lockMutexInit = GL_TRUE;
_glthread_INIT_MUTEX(lockMutex);
}
ctx->Const.MaxTextureMaxAnisotropy = 2.0;
@@ -317,6 +326,8 @@ GLboolean intelInitContext( intelContextPtr intel,
ctx->Const.MaxPointSizeAA = 3.0;
ctx->Const.PointSizeGranularity = 1.0;
ctx->Const.MaxColorAttachments = 4; /* XXX FBO: review this */
/* Initialize the software rasterizer and helper modules. */
_swrast_CreateContext( ctx );
_ac_CreateContext( ctx );
@@ -336,23 +347,16 @@ GLboolean intelInitContext( intelContextPtr intel,
intel->driFd = sPriv->fd;
intel->driHwLock = (drmLock *) &sPriv->pSAREA->lock;
intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
intel->hw_stipple = 1;
/* XXX FBO: this doesn't seem to be used anywhere */
switch(mesaVis->depthBits) {
case 0: /* what to do in this case? */
case 16:
intel->depth_scale = 1.0/0xffff;
intel->polygon_offset_scale = 1.0/0xffff;
intel->depth_clear_mask = ~0;
intel->ClearDepth = 0xffff;
break;
case 24:
intel->depth_scale = 1.0/0xffffff;
intel->polygon_offset_scale = 2.0/0xffffff; /* req'd to pass glean */
intel->depth_clear_mask = 0x00ffffff;
intel->stencil_clear_mask = 0xff000000;
intel->ClearDepth = 0x00ffffff;
break;
default:
assert(0);
@@ -371,7 +375,65 @@ GLboolean intelInitContext( intelContextPtr intel,
_math_matrix_ctr (&intel->ViewportMatrix);
driInitExtensions( ctx, card_extensions, GL_TRUE );
/* Disable imaging extension until convolution is working in
* teximage paths:
*/
driInitExtensions( ctx, card_extensions,
/* GL_TRUE, */
GL_FALSE);
/* Buffer manager:
*/
intel->bm = bm_intel_Attach( intel );
#if 0
bmInitPool(intel->bm,
intel->intelScreen->tex.offset, /* low offset */
intel->intelScreen->tex.map, /* low virtual */
intel->intelScreen->tex.size,
DRM_MM_TT);
#endif
/* XXX FBO: these have to go away!
* FBO regions should be setup when creating the drawable. */
/* These are still static, but create regions for them.
*/
intel->front_region =
intel_region_create_static(intel,
DRM_MM_TT,
intelScreen->front.offset,
intelScreen->front.map,
intelScreen->cpp,
intelScreen->front.pitch,
intelScreen->height);
intel->back_region =
intel_region_create_static(intel,
DRM_MM_TT,
intelScreen->back.offset,
intelScreen->back.map,
intelScreen->cpp,
intelScreen->back.pitch,
intelScreen->height);
/* Still assuming front.cpp == depth.cpp
*/
intel->depth_region =
intel_region_create_static(intel,
DRM_MM_TT,
intelScreen->depth.offset,
intelScreen->depth.map,
intelScreen->cpp,
intelScreen->depth.pitch,
intelScreen->height);
intel->batch = intel_batchbuffer_alloc( intel );
intel->last_swap_fence_retired = GL_TRUE;
intel->last_swap_fence = bmInitFence(intel->bm);
intel_bufferobj_init( intel );
intel_fbo_init( intel );
if (intel->ctx.Mesa_DXTn) {
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
@@ -381,30 +443,15 @@ GLboolean intelInitContext( intelContextPtr intel,
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
}
/* driInitTextureObjects( ctx, & intel->swapped, */
/* DRI_TEXMGR_DO_TEXTURE_1D | */
/* DRI_TEXMGR_DO_TEXTURE_2D | */
/* DRI_TEXMGR_DO_TEXTURE_RECT ); */
intel->prim.flush = intelInitBatchBuffer;
intel->prim.primitive = ~0;
#if DO_DEBUG
INTEL_DEBUG = driParseDebugString( getenv( "INTEL_DEBUG" ),
debug_control );
INTEL_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
debug_control );
#endif
#ifndef VERBOSE
if (getenv("INTEL_VERBOSE"))
VERBOSE=1;
#endif
if (getenv("INTEL_NO_RAST") ||
getenv("INTEL_NO_RAST")) {
if (getenv("INTEL_NO_RAST")) {
fprintf(stderr, "disabling 3D rasterization\n");
FALLBACK(intel, INTEL_FALLBACK_USER, 1);
}
@@ -414,7 +461,7 @@ GLboolean intelInitContext( intelContextPtr intel,
void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
{
intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate;
assert(intel); /* should never be null */
if (intel) {
@@ -431,121 +478,19 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
_swrast_DestroyContext (&intel->ctx);
intel->Fallback = 0; /* don't call _swrast_Flush later */
intelDestroyBatchBuffer(&intel->ctx);
intel_batchbuffer_free(intel->batch);
if ( release_texture_heaps ) {
/* This share group is about to go away, free our private
* texture object data.
*/
int i;
for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
driDestroyTextureHeap( intel->texture_heaps[ i ] );
intel->texture_heaps[ i ] = NULL;
}
assert( is_empty_list( & intel->swapped ) );
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "do something to free texture heaps\n");
}
/* free the Mesa context */
_mesa_destroy_context(&intel->ctx);
}
}
void intelSetFrontClipRects( intelContextPtr intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
}
void intelSetBackClipRects( intelContextPtr intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
} else {
intel->numClipRects = dPriv->numBackClipRects;
intel->pClipRects = dPriv->pBackClipRects;
intel->drawX = dPriv->backX;
intel->drawY = dPriv->backY;
if (dPriv->numBackClipRects == 1 &&
dPriv->x == dPriv->backX &&
dPriv->y == dPriv->backY) {
/* Repeat the calculation of the back cliprect dimensions here
* as early versions of dri.a in the Xserver are incorrect. Try
* very hard not to restrict future versions of dri.a which
* might eg. allocate truly private back buffers.
*/
int x1, y1;
int x2, y2;
x1 = dPriv->x;
y1 = dPriv->y;
x2 = dPriv->x + dPriv->w;
y2 = dPriv->y + dPriv->h;
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
if (x1 == dPriv->pBackClipRects[0].x1 &&
y1 == dPriv->pBackClipRects[0].y1) {
dPriv->pBackClipRects[0].x2 = x2;
dPriv->pBackClipRects[0].y2 = y2;
}
}
}
}
void intelWindowMoved( intelContextPtr intel )
{
if (!intel->ctx.DrawBuffer) {
intelSetFrontClipRects( intel );
}
else {
switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
case BUFFER_BIT_FRONT_LEFT:
intelSetFrontClipRects( intel );
break;
case BUFFER_BIT_BACK_LEFT:
intelSetBackClipRects( intel );
break;
default:
/* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
intelSetFrontClipRects( intel );
}
}
/* Set state we know depends on drawable parameters:
*/
{
GLcontext *ctx = &intel->ctx;
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
ctx->Driver.DepthRange( ctx,
ctx->Viewport.Near,
ctx->Viewport.Far );
_mesa_free_context_data(&intel->ctx);
}
}
@@ -560,7 +505,9 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
{
if (driContextPriv) {
intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate;
GLframebuffer *drawFb = (GLframebuffer *) driDrawPriv->driverPrivate;
GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate;
if ( intel->driDrawable != driDrawPriv ) {
/* Shouldn't the readbuffer be stored also? */
@@ -568,28 +515,53 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
intelWindowMoved( intel );
}
_mesa_make_current(&intel->ctx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate);
/* XXX FBO temporary fix-ups! */
/* if the renderbuffers don't have regions, init them from the context */
{
struct intel_renderbuffer *irbFront
= intel_get_renderbuffer(drawFb, BUFFER_FRONT_LEFT);
struct intel_renderbuffer *irbBack
= intel_get_renderbuffer(drawFb, BUFFER_BACK_LEFT);
struct intel_renderbuffer *irbDepth
= intel_get_renderbuffer(drawFb, BUFFER_DEPTH);
struct intel_renderbuffer *irbStencil
= intel_get_renderbuffer(drawFb, BUFFER_STENCIL);
intel->ctx.Driver.DrawBuffer( &intel->ctx, intel->ctx.Color.DrawBuffer[0] );
} else {
if (irbFront && !irbFront->region) {
intel_region_reference(&irbFront->region, intel->front_region);
}
if (irbBack && !irbBack->region) {
intel_region_reference(&irbBack->region, intel->back_region);
}
if (irbDepth && !irbDepth->region) {
intel_region_reference(&irbDepth->region, intel->depth_region);
}
if (irbStencil && !irbStencil->region) {
intel_region_reference(&irbStencil->region, intel->depth_region);
}
}
_mesa_make_current(&intel->ctx, drawFb, readFb);
intel_draw_buffer(&intel->ctx, drawFb);
}
else {
_mesa_make_current(NULL, NULL, NULL);
}
return GL_TRUE;
}
void intelGetLock( intelContextPtr intel, GLuint flags )
void intelGetLock( struct intel_context *intel, GLuint flags )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
__DRIscreenPrivate *sPriv = intel->driScreen;
drmI830Sarea * sarea = intel->sarea;
int me = intel->hHWContext;
unsigned i;
drmGetLock(intel->driFd, intel->hHWContext, flags);
/* If the window moved, may need to set a new cliprect now.
*
* NOTE: This releases and regains the hw lock, so all state
@@ -598,143 +570,19 @@ void intelGetLock( intelContextPtr intel, GLuint flags )
if (dPriv)
DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
/* If we lost context, need to dump all registers to hardware.
* Note that we don't care about 2d contexts, even if they perform
* accelerated commands, so the DRI locking in the X server is even
* more broken than usual.
/* Lost context?
*/
if (sarea->ctxOwner != me) {
intel->perf_boxes |= I830_BOX_LOST_CONTEXT;
sarea->ctxOwner = me;
}
/* Shared texture managment - if another client has played with
* texture space, figure out which if any of our textures have been
* ejected, and update our global LRU.
/* Drawable changed?
*/
for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
DRI_AGE_TEXTURES( intel->texture_heaps[ i ] );
}
if (dPriv && intel->lastStamp != dPriv->lastStamp) {
intelWindowMoved( intel );
intel->lastStamp = dPriv->lastStamp;
}
}
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
intelContextPtr intel;
GLcontext *ctx;
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
ctx = &intel->ctx;
if (ctx->Visual.doubleBufferMode) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
intelPageFlip( dPriv );
} else {
intelCopyBuffer( dPriv );
}
}
} else {
/* XXX this shouldn't be an error but we can't handle it for now */
fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
}
}
void intelInitState( GLcontext *ctx )
{
/* Mesa should do this for us:
*/
ctx->Driver.AlphaFunc( ctx,
ctx->Color.AlphaFunc,
ctx->Color.AlphaRef);
ctx->Driver.BlendColor( ctx,
ctx->Color.BlendColor );
ctx->Driver.BlendEquationSeparate( ctx,
ctx->Color.BlendEquationRGB,
ctx->Color.BlendEquationA);
ctx->Driver.BlendFuncSeparate( ctx,
ctx->Color.BlendSrcRGB,
ctx->Color.BlendDstRGB,
ctx->Color.BlendSrcA,
ctx->Color.BlendDstA);
ctx->Driver.ColorMask( ctx,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
ctx->Color.ColorMask[BCOMP],
ctx->Color.ColorMask[ACOMP]);
ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode );
ctx->Driver.DepthFunc( ctx, ctx->Depth.Func );
ctx->Driver.DepthMask( ctx, ctx->Depth.Mask );
ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag );
ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled );
ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled );
ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace );
{
GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
}
ctx->Driver.LineWidth( ctx, ctx->Line.Width );
ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp );
ctx->Driver.PointSize( ctx, ctx->Point.Size );
ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple );
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel );
ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT,
ctx->Stencil.Function[0],
ctx->Stencil.Ref[0],
ctx->Stencil.ValueMask[0] );
ctx->Driver.StencilFuncSeparate( ctx, GL_BACK,
ctx->Stencil.Function[1],
ctx->Stencil.Ref[1],
ctx->Stencil.ValueMask[1] );
ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
ctx->Driver.StencilOpSeparate( ctx, GL_FRONT,
ctx->Stencil.FailFunc[0],
ctx->Stencil.ZFailFunc[0],
ctx->Stencil.ZPassFunc[0]);
ctx->Driver.StencilOpSeparate( ctx, GL_BACK,
ctx->Stencil.FailFunc[1],
ctx->Stencil.ZFailFunc[1],
ctx->Stencil.ZPassFunc[1]);
ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
}

View File

@@ -47,82 +47,122 @@
#define DV_PF_565 (2<<8)
#define DV_PF_8888 (3<<8)
#define INTEL_CONTEXT(ctx) ((intelContextPtr)(ctx))
struct intel_region;
struct intel_context;
typedef struct intel_context intelContext;
typedef struct intel_context *intelContextPtr;
typedef struct intel_texture_object *intelTextureObjectPtr;
typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *,
typedef void (*intel_tri_func)(struct intel_context *, intelVertex *, intelVertex *,
intelVertex *);
typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *);
typedef void (*intel_point_func)(intelContextPtr, intelVertex *);
typedef void (*intel_line_func)(struct intel_context *, intelVertex *, intelVertex *);
typedef void (*intel_point_func)(struct intel_context *, intelVertex *);
#define INTEL_FALLBACK_DRAW_BUFFER 0x1
#define INTEL_FALLBACK_READ_BUFFER 0x2
#define INTEL_FALLBACK_USER 0x4
#define INTEL_FALLBACK_NO_BATCHBUFFER 0x8
#define INTEL_FALLBACK_NO_TEXMEM 0x10
#define INTEL_FALLBACK_DEPTH_BUFFER 0x4
#define INTEL_FALLBACK_STENCIL_BUFFER 0x8
#define INTEL_FALLBACK_USER 0x10
#define INTEL_FALLBACK_RENDERMODE 0x20
extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode );
extern void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode );
#define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode )
#define INTEL_TEX_MAXLEVELS 10
struct intel_texture_object
{
driTextureObject base; /* the parent class */
struct gl_texture_object base; /* The "parent" object */
GLuint texelBytes;
GLuint age;
GLuint Pitch;
GLuint Height;
GLuint TextureOffset;
GLubyte *BufAddr;
/* The mipmap tree must include at least these levels once
* validated:
*/
GLuint firstLevel;
GLuint lastLevel;
GLuint min_level;
GLuint max_level;
GLuint depth_pitch;
/* Offset for firstLevel image:
*/
GLuint textureOffset;
struct {
const struct gl_texture_image *image;
GLuint offset; /* into BufAddr */
GLuint height;
GLuint internalFormat;
} image[6][INTEL_TEX_MAXLEVELS];
GLuint dirty;
GLuint firstLevel,lastLevel;
/* On validation any active images held in main memory or in other
* regions will be copied to this region and the old storage freed.
*/
struct intel_mipmap_tree *mt;
};
struct intel_texture_image
{
struct gl_texture_image base;
/* These aren't stored in gl_texture_image
*/
GLuint level;
GLuint face;
/* If intelImage->mt != NULL, image data is stored here.
* Else if intelImage->base.Data != NULL, image is stored there.
* Else there is no image data.
*/
struct intel_mipmap_tree *mt;
};
#define INTEL_MAX_FIXUP 64
struct intel_context
{
GLcontext ctx; /* the parent class */
struct {
void (*destroy)( intelContextPtr intel );
void (*emit_state)( intelContextPtr intel );
void (*emit_invarient_state)( intelContextPtr intel );
void (*lost_hardware)( intelContextPtr intel );
void (*update_texture_state)( intelContextPtr intel );
void (*destroy)( struct intel_context *intel );
void (*emit_state)( struct intel_context *intel );
void (*lost_hardware)( struct intel_context *intel );
void (*update_texture_state)( struct intel_context *intel );
void (*render_start)( intelContextPtr intel );
void (*set_draw_offset)( intelContextPtr intel, int offset );
void (*emit_flush)( intelContextPtr intel );
void (*render_start)( struct intel_context *intel );
void (*set_draw_region)( struct intel_context *intel,
struct intel_region *draw_region,
struct intel_region *depth_region );
void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim );
GLuint (*flush_cmd)( void );
GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected );
void (*reduced_primitive_state)( struct intel_context *intel, GLenum rprim );
void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch);
GLboolean (*check_vertex_size)( struct intel_context *intel, GLuint expected );
intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj );
/* Metaops:
*/
void (*install_meta_state)( struct intel_context *intel );
void (*leave_meta_state)( struct intel_context *intel );
void (*meta_draw_region)( struct intel_context *intel,
struct intel_region *draw_region,
struct intel_region *depth_region );
void (*meta_color_mask)( struct intel_context *intel,
GLboolean );
void (*meta_stencil_replace)( struct intel_context *intel,
GLuint mask,
GLuint clear );
void (*meta_depth_replace)( struct intel_context *intel );
void (*meta_texture_blend_replace)( struct intel_context *intel );
void (*meta_no_stencil_write)( struct intel_context *intel );
void (*meta_no_depth_write)( struct intel_context *intel );
void (*meta_no_texture)( struct intel_context *intel );
void (*meta_import_pixel_state)( struct intel_context *intel );
GLboolean (*meta_tex_rect_source)( struct intel_context *intel,
GLuint buffer,
GLuint offset,
GLuint pitch,
GLuint height,
GLenum format,
GLenum type);
} vtbl;
@@ -130,63 +170,44 @@ struct intel_context
GLuint Fallback;
GLuint NewGLState;
struct {
GLuint start_offset;
GLint size;
GLint space;
GLubyte *ptr;
} batch;
struct {
void *ptr;
GLint size;
GLuint offset;
GLuint active_buf;
GLuint irq_emitted;
} alloc;
GLuint last_fence;
GLuint last_swap_fence;
GLboolean last_swap_fence_retired;
struct intel_batchbuffer *batch;
struct {
GLuint id;
GLuint primitive;
GLubyte *start_ptr;
void (*flush)( GLcontext * );
void (*flush)( struct intel_context * );
} prim;
GLboolean locked;
char *prevLockFile;
int prevLockLine;
GLubyte clear_red;
GLubyte clear_green;
GLubyte clear_blue;
GLubyte clear_alpha;
GLuint ClearColor;
GLuint ClearDepth;
GLuint ClearColor565;
GLuint ClearColor8888;
/* Offsets of fields within the current vertex:
*/
GLuint coloroffset;
GLuint specoffset;
/* Support for duplicating XYZW as WPOS parameter (crutch for I915).
*/
GLuint wpos_offset;
GLuint wpos_size;
struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
GLuint vertex_attr_count;
GLfloat depth_scale;
GLfloat polygon_offset_scale; /* dependent on depth_scale, bpp */
GLuint depth_clear_mask;
GLuint stencil_clear_mask;
GLboolean hw_stencil;
GLboolean hw_stipple;
/* Texture object bookkeeping
/* AGP memory buffer manager:
*/
GLuint nr_heaps;
driTexHeap * texture_heaps[1];
driTextureObject swapped;
GLuint lastStamp;
struct bufmgr *bm;
struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS];
/* State for intelvb.c and inteltris.c.
*/
@@ -195,7 +216,13 @@ struct intel_context
GLenum render_primitive;
GLenum reduced_primitive;
GLuint vertex_size;
char *verts; /* points to tnl->clipspace.vertex_buf */
GLubyte *verts; /* points to tnl->clipspace.vertex_buf */
struct intel_region *front_region; /* XXX FBO: obsolete */
struct intel_region *back_region; /* XXX FBO: obsolete */
struct intel_region *draw_region; /* XXX FBO: rename to color_region */
struct intel_region *depth_region; /**< currently bound depth/Z region */
/* Fallback rasterization functions
@@ -204,21 +231,22 @@ struct intel_context
intel_line_func draw_line;
intel_tri_func draw_tri;
/* These refer to the current draw (front vs. back) buffer:
/* These refer to the current drawing buffer:
*/
GLuint drawOffset; /* agp offset of drawbuffer */
int drawX; /* origin of drawable in draw buffer */
int drawY;
GLuint numClipRects; /* cliprects for that buffer */
int drawX, drawY; /**< origin of drawing area within region */
GLuint numClipRects; /**< cliprects for drawing */
drm_clip_rect_t *pClipRects;
drm_clip_rect_t fboRect; /**< cliprect for FBO rendering */
int dirtyAge;
int perf_boxes;
int do_irqs;
/* XXX these seem to be unused */
#if 0
GLboolean scissor;
drm_clip_rect_t draw_rect;
drm_clip_rect_t scissor_rect;
#endif
drm_context_t hHWContext;
drmLock *driHwLock;
@@ -228,6 +256,8 @@ struct intel_context
__DRIscreenPrivate *driScreen;
intelScreenPrivate *intelScreen;
drmI830Sarea *sarea;
GLuint lastStamp;
/**
* Configuration cache
@@ -236,22 +266,20 @@ struct intel_context
};
#define DEBUG_LOCKING 1
#define DEBUG_LOCKING 1
#if DEBUG_LOCKING
extern char *prevLockFile;
extern int prevLockLine;
#define DEBUG_LOCK() \
do { \
prevLockFile = (__FILE__); \
prevLockLine = (__LINE__); \
intel->prevLockFile = (__FILE__); \
intel->prevLockLine = (__LINE__); \
} while (0)
#define DEBUG_RESET() \
do { \
prevLockFile = 0; \
prevLockLine = 0; \
intel->prevLockFile = 0; \
intel->prevLockLine = 0; \
} while (0)
/* Slightly less broken way of detecting recursive locking in a
@@ -270,7 +298,8 @@ extern int prevLockLine;
(DRM_LOCK_HELD | intel->hHWContext) ) { \
fprintf( stderr, \
"LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
intel->prevLockFile, intel->prevLockLine, \
__FILE__, __LINE__ ); \
abort(); \
} \
} while (0)
@@ -283,7 +312,7 @@ extern int prevLockLine;
#endif
extern _glthread_Mutex lockMutex;
/* Lock the hardware and validate our state.
@@ -291,13 +320,14 @@ extern int prevLockLine;
#define LOCK_HARDWARE( intel ) \
do { \
char __ret=0; \
_glthread_LOCK_MUTEX(lockMutex); \
DEBUG_CHECK_LOCK(); \
assert(!(intel)->locked); \
DRM_CAS((intel)->driHwLock, (intel)->hHWContext, \
(DRM_LOCK_HELD|(intel)->hHWContext), __ret); \
if (__ret) \
intelGetLock( (intel), 0 ); \
DEBUG_LOCK(); \
DEBUG_LOCK(); \
(intel)->locked = 1; \
}while (0)
@@ -313,6 +343,7 @@ do { \
} \
DRM_UNLOCK((intel)->driFd, (intel)->driHwLock, (intel)->hHWContext); \
DEBUG_RESET(); \
_glthread_UNLOCK_MUTEX(lockMutex); \
} while (0)
@@ -321,8 +352,7 @@ do { \
#define INTEL_FIREVERTICES(intel) \
do { \
if ((intel)->prim.flush) \
(intel)->prim.flush(&(intel)->ctx); \
assert(!(intel)->prim.flush); \
} while (0)
/* ================================================================
@@ -343,20 +373,14 @@ do { \
((a<<24) | (r<<16) | (g<<8) | b)
#define INTEL_PACKCOLOR(format, r, g, b, a) \
(format == DV_PF_555 ? INTEL_PACKCOLOR1555(r,g,b,a) : \
(format == DV_PF_565 ? INTEL_PACKCOLOR565(r,g,b) : \
(format == DV_PF_8888 ? INTEL_PACKCOLOR8888(r,g,b,a) : \
0)))
/* ================================================================
* From linux kernel i386 header files, copes with odd sizes better
* than COPY_DWORDS would:
* XXX Put this in src/mesa/main/imports.h ???
*/
#if defined(i386) || defined(__i386__)
static __inline__ void * __memcpy(void * to, const void * from, size_t n)
static INLINE void * __memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
@@ -417,21 +441,19 @@ extern int INTEL_DEBUG;
* intel_context.c:
*/
extern void intelInitDriverFunctions( struct dd_function_table *functions );
extern GLboolean intelInitContext( intelContextPtr intel,
extern GLboolean intelInitContext( struct intel_context *intel,
const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate,
struct dd_function_table *functions );
extern void intelGetLock(intelContextPtr intel, GLuint flags);
extern void intelSetBackClipRects(intelContextPtr intel);
extern void intelSetFrontClipRects(intelContextPtr intel);
extern void intelWindowMoved( intelContextPtr intel );
extern void intelGetLock(struct intel_context *intel, GLuint flags);
extern void intelInitState( GLcontext *ctx );
extern const GLubyte *intelGetString( GLcontext *ctx, GLenum name );
extern void intelFinish( GLcontext *ctx );
extern void intelFlush( GLcontext *ctx );
extern void intelInitDriverFunctions( struct dd_function_table *functions );
/* ================================================================
@@ -491,6 +513,8 @@ extern void intelInitStateFuncs( struct dd_function_table *functions );
#define BLENDFACT_INV_CONST_ALPHA 0x0f
#define BLENDFACT_MASK 0x0f
#define MI_BATCH_BUFFER_END (0xA<<23)
extern int intel_translate_compare_func( GLenum func );
extern int intel_translate_stencil_op( GLenum op );
@@ -498,19 +522,26 @@ extern int intel_translate_blend_factor( GLenum factor );
extern int intel_translate_logic_op( GLenum opcode );
/* ================================================================
* intel_ioctl.c:
/*======================================================================
* Inline conversion functions.
* These are better-typed than the macros used previously:
*/
extern void intel_dump_batchbuffer( long offset,
int *ptr,
int count );
static INLINE struct intel_context *intel_context( GLcontext *ctx )
{
return (struct intel_context *)ctx;
}
static INLINE struct intel_texture_object *intel_texture_object( struct gl_texture_object *obj )
{
return (struct intel_texture_object *)obj;
}
/* ================================================================
* intel_pixel.c:
*/
extern void intelInitPixelFuncs( struct dd_function_table *functions );
static INLINE struct intel_texture_image *intel_texture_image( struct gl_texture_image *img )
{
return (struct intel_texture_image *)img;
}
extern struct intel_renderbuffer *intel_renderbuffer( struct gl_renderbuffer *rb );
#endif

View File

@@ -0,0 +1,281 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "glheader.h"
#include "imports.h"
#include "context.h"
#include "depthstencil.h"
#include "fbobject.h"
#include "framebuffer.h"
#include "hash.h"
#include "mtypes.h"
#include "renderbuffer.h"
#include "intel_context.h"
#include "intel_fbo.h"
#include "intel_depthstencil.h"
#include "intel_regions.h"
/**
* The GL_EXT_framebuffer_object allows the user to create their own
* framebuffer objects consisting of color renderbuffers (0 or more),
* depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1).
*
* The spec considers depth and stencil renderbuffers to be totally independent
* buffers. In reality, most graphics hardware today uses a combined
* depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil).
*
* This causes difficulty because the user may create some number of depth
* renderbuffers and some number of stencil renderbuffers and bind them
* together in framebuffers in any combination.
*
* This code manages all that.
*
* 1. Depth renderbuffers are always allocated in hardware as 32bpp
* GL_DEPTH24_STENCIL8 buffers.
*
* 2. Stencil renderbuffers are initially allocated in software as 8bpp
* GL_STENCIL_INDEX8 buffers.
*
* 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth
* fields (respectively) to indicate if the buffer's currently paired
* with another stencil or depth buffer (respectively).
*
* 4. When a depth and stencil buffer are initially both attached to the
* current framebuffer, we merge the stencil buffer values into the
* depth buffer (really a depth+stencil buffer). The then hardware uses
* the combined buffer.
*
* 5. Whenever a depth or stencil buffer is reallocated (with
* glRenderbufferStorage) we undo the pairing and copy the stencil values
* from the combined depth/stencil buffer back to the stencil-only buffer.
*
* 6. We also undo the pairing when we find a change in buffer bindings.
*
* 7. If a framebuffer is only using a depth renderbuffer (no stencil), we
* just use the combined depth/stencil buffer and ignore the stencil values.
*
* 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have
* to promote the 8bpp software stencil buffer to a 32bpp hardware
* depth+stencil buffer.
*
*/
static void
map_regions(GLcontext *ctx,
struct intel_renderbuffer *depthRb,
struct intel_renderbuffer *stencilRb)
{
struct intel_context *intel = intel_context(ctx);
if (depthRb && depthRb->region) {
intel_region_map(intel, depthRb->region);
depthRb->pfMap = depthRb->region->map;
depthRb->pfPitch = depthRb->region->pitch;
}
if (stencilRb && stencilRb->region) {
intel_region_map(intel, stencilRb->region);
stencilRb->pfMap = stencilRb->region->map;
stencilRb->pfPitch = stencilRb->region->pitch;
}
}
static void
unmap_regions(GLcontext *ctx,
struct intel_renderbuffer *depthRb,
struct intel_renderbuffer *stencilRb)
{
struct intel_context *intel = intel_context(ctx);
if (depthRb && depthRb->region) {
intel_region_unmap(intel, depthRb->region);
depthRb->pfMap = NULL;
depthRb->pfPitch = 0;
}
if (stencilRb && stencilRb->region) {
intel_region_unmap(intel, stencilRb->region);
stencilRb->pfMap = NULL;
stencilRb->pfPitch = 0;
}
}
/**
* Undo the pairing/interleaving between depth and stencil buffers.
* irb should be a depth/stencil or stencil renderbuffer.
*/
void
intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb)
{
if (irb->PairedStencil) {
/* irb is a depth/stencil buffer */
struct gl_renderbuffer *stencilRb;
struct intel_renderbuffer *stencilIrb;
ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil);
stencilIrb = intel_renderbuffer(stencilRb);
if (stencilIrb) {
/* need to extract stencil values from the depth buffer */
ASSERT(stencilIrb->PairedDepth == irb->Base.Name);
map_regions(ctx, irb, stencilIrb);
_mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base);
unmap_regions(ctx, irb, stencilIrb);
stencilIrb->PairedDepth = 0;
}
irb->PairedStencil = 0;
}
else if (irb->PairedDepth) {
/* irb is a stencil buffer */
struct gl_renderbuffer *depthRb;
struct intel_renderbuffer *depthIrb;
ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth);
depthIrb = intel_renderbuffer(depthRb);
if (depthIrb) {
/* need to extract stencil values from the depth buffer */
ASSERT(depthIrb->PairedStencil == irb->Base.Name);
map_regions(ctx, depthIrb, irb);
_mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base);
unmap_regions(ctx, depthIrb, irb);
depthIrb->PairedStencil = 0;
}
irb->PairedDepth = 0;
}
else {
_mesa_problem(ctx, "Problem in undo_depth_stencil_pairing");
}
ASSERT(irb->PairedStencil == 0);
ASSERT(irb->PairedDepth == 0);
}
/**
* Examine the depth and stencil renderbuffers which are attached to the
* framebuffer. If both depth and stencil are attached, make sure that the
* renderbuffers are 'paired' (combined). If only depth or only stencil is
* attached, undo any previous pairing.
*
* Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments
* change, for example).
*/
void
intel_validate_paired_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb)
{
struct intel_renderbuffer *depthRb, *stencilRb;
depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
if (depthRb && stencilRb) {
if (depthRb == stencilRb) {
/* Using a user-created combined depth/stencil buffer.
* Nothing to do.
*/
ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT);
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
}
else {
/* Separate depth/stencil buffers, need to interleave now */
ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT);
ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX);
/* may need to interleave depth/stencil now */
if (depthRb->PairedStencil == stencilRb->Base.Name) {
/* OK, the depth and stencil buffers are already interleaved */
ASSERT(stencilRb->PairedDepth == depthRb->Base.Name);
}
else {
/* need to setup new pairing/interleaving */
if (depthRb->PairedStencil) {
intel_unpair_depth_stencil(ctx, depthRb);
}
if (stencilRb->PairedDepth) {
intel_unpair_depth_stencil(ctx, stencilRb);
}
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
/* establish new pairing: interleave stencil into depth buffer */
map_regions(ctx, depthRb, stencilRb);
_mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base);
unmap_regions(ctx, depthRb, stencilRb);
depthRb->PairedStencil = stencilRb->Base.Name;
stencilRb->PairedDepth = depthRb->Base.Name;
}
}
}
else if (depthRb) {
/* Depth buffer but no stencil buffer.
* We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits.
*/
/* can't assert this until storage is allocated:
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
*/
/* intel_undo any previous pairing */
if (depthRb->PairedStencil) {
intel_unpair_depth_stencil(ctx, depthRb);
}
}
else if (stencilRb) {
/* Stencil buffer but no depth buffer.
* Since h/w doesn't typically support just 8bpp stencil w/out Z,
* we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits.
*/
/* undo any previous pairing */
if (stencilRb->PairedDepth) {
intel_unpair_depth_stencil(ctx, stencilRb);
}
if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) {
/* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */
_mesa_promote_stencil(ctx, &stencilRb->Base);
ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
}
}
/* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */
_mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
if (depthRb && depthRb->PairedStencil)
_mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH);
else
_mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);
/* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer
* first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer
* if present.
*/
}

View File

@@ -0,0 +1,13 @@
#ifndef INTEL_DEPTH_STENCIL_H
#define INTEL_DEPTH_STENCIL_H
extern void
intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb);
extern void
intel_validate_paired_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb);
#endif /* INTEL_DEPTH_STENCIL_H */

View File

@@ -0,0 +1,638 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "imports.h"
#include "mtypes.h"
#include "fbobject.h"
#include "framebuffer.h"
#include "renderbuffer.h"
#include "context.h"
#include "texformat.h"
#include "texrender.h"
#include "intel_context.h"
#include "intel_buffers.h"
#include "intel_bufmgr.h"
#include "intel_depthstencil.h"
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_span.h"
#define INTEL_RB_CLASS 0x12345678
/* XXX FBO: move this to intel_context.h (inlined) */
/**
* Return a gl_renderbuffer ptr casted to intel_renderbuffer.
* NULL will be returned if the rb isn't really an intel_renderbuffer.
* This is determiend by checking the ClassID.
*/
struct intel_renderbuffer *intel_renderbuffer( struct gl_renderbuffer *rb )
{
struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
/*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
return irb;
}
else
return NULL;
}
struct intel_renderbuffer *
intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex)
{
return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
}
struct intel_region *
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
{
struct intel_renderbuffer *irb
= intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
if (irb)
return irb->region;
else
return NULL;
}
/**
* Create a new framebuffer object.
*/
static struct gl_framebuffer *
intel_new_framebuffer(GLcontext *ctx, GLuint name)
{
/* there's no intel_framebuffer at this time, just use Mesa's class */
return _mesa_new_framebuffer(ctx, name);
}
static void
intel_delete_renderbuffer(struct gl_renderbuffer *rb)
{
GET_CURRENT_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
ASSERT(irb);
if (irb->PairedStencil || irb->PairedDepth) {
intel_unpair_depth_stencil(ctx, irb);
}
if (intel && irb->region) {
intel_region_release(intel, &irb->region);
}
_mesa_free(irb);
}
/**
* Return a pointer to a specific pixel in a renderbuffer.
*/
static void *
intel_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
/* By returning NULL we force all software rendering to go through
* the span routines.
*/
return NULL;
}
/**
* Called via glRenderbufferStorageEXT() to set the format and allocate
* storage for a user-created renderbuffer.
*/
static GLboolean
intel_alloc_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
GLboolean softwareBuffer = GL_FALSE;
int cpp;
ASSERT(rb->Name != 0);
switch (internalFormat) {
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
rb->_ActualFormat = GL_RGB5;
rb->DataType = GL_UNSIGNED_BYTE;
rb->RedBits = 5;
rb->GreenBits = 6;
rb->BlueBits = 5;
cpp = 2;
break;
case GL_RGB:
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
case GL_RGBA:
case GL_RGBA2:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
rb->_ActualFormat = GL_RGBA8;
rb->DataType = GL_UNSIGNED_BYTE;
rb->RedBits = 8;
rb->GreenBits = 8;
rb->BlueBits = 8;
rb->AlphaBits = 8;
cpp = 4;
break;
case GL_STENCIL_INDEX:
case GL_STENCIL_INDEX1_EXT:
case GL_STENCIL_INDEX4_EXT:
case GL_STENCIL_INDEX8_EXT:
case GL_STENCIL_INDEX16_EXT:
/* alloc a depth+stencil buffer */
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->StencilBits = 8;
cpp = 4;
break;
case GL_DEPTH_COMPONENT16:
rb->_ActualFormat = GL_DEPTH_COMPONENT16;
rb->DataType = GL_UNSIGNED_SHORT;
rb->DepthBits = 16;
cpp = 2;
break;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->DepthBits = 24;
cpp = 4;
break;
case GL_DEPTH_STENCIL_EXT:
case GL_DEPTH24_STENCIL8_EXT:
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->DepthBits = 24;
rb->StencilBits = 8;
cpp = 4;
break;
default:
_mesa_problem(ctx, "Unexpected format in intel_alloc_renderbuffer_storage");
return GL_FALSE;
}
intelFlush(ctx);
/* free old region */
if (irb->region) {
/*LOCK_HARDWARE(intel);*/
intel_region_release(intel, &irb->region);
/*UNLOCK_HARDWARE(intel);*/
}
/* allocate new memory region/renderbuffer */
if (softwareBuffer) {
return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
width, height);
}
else {
/* Choose a pitch to match hardware requirements:
*/
GLuint pitch = ((cpp * width + 63) & ~63) / cpp;
/* alloc hardware renderbuffer */
_mesa_debug(ctx, "Allocating %d x %d Intel RBO (pitch %d)\n", width, height, pitch);
irb->region = intel_region_alloc(intel, cpp, pitch, height);
if (!irb->region)
return GL_FALSE; /* out of memory? */
ASSERT(irb->region->buffer);
rb->Width = width;
rb->Height = height;
/* This sets the Get/PutRow/Value functions */
intel_set_span_functions(&irb->Base);
return GL_TRUE;
}
}
/**
* Called for each hardware renderbuffer when a _window_ is resized.
* Just update fields.
* Not used for user-created renderbuffers!
*/
static GLboolean
intel_alloc_window_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
ASSERT(rb->Name == 0);
rb->Width = width;
rb->Height = height;
rb->_ActualFormat = internalFormat;
return GL_TRUE;
}
static GLboolean
intel_nop_alloc_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
_mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
return GL_FALSE;
}
/**
* Create a new intel_renderbuffer which corresponds to an on-screen window,
* not a user-created renderbuffer.
* \param width the screen width
* \param height the screen height
*/
struct intel_renderbuffer *
intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
int offset, int pitch, int cpp, void *map)
{
GET_CURRENT_CONTEXT(ctx);
struct intel_renderbuffer *irb;
const GLuint name = 0;
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
return NULL;
}
_mesa_init_renderbuffer(&irb->Base, name);
irb->Base.ClassID = INTEL_RB_CLASS;
switch (intFormat) {
case GL_RGB5:
irb->Base._ActualFormat = GL_RGB5;
irb->Base._BaseFormat = GL_RGBA;
irb->Base.RedBits = 5;
irb->Base.GreenBits = 6;
irb->Base.BlueBits = 5;
irb->Base.DataType = GL_UNSIGNED_BYTE;
cpp = 2;
break;
case GL_RGBA8:
irb->Base._ActualFormat = GL_RGBA8;
irb->Base._BaseFormat = GL_RGBA;
irb->Base.RedBits = 8;
irb->Base.GreenBits = 8;
irb->Base.BlueBits = 8;
irb->Base.AlphaBits = 8;
irb->Base.DataType = GL_UNSIGNED_BYTE;
cpp = 4;
break;
case GL_STENCIL_INDEX8_EXT:
irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
irb->Base._BaseFormat = GL_STENCIL_INDEX;
irb->Base.StencilBits = 8;
irb->Base.DataType = GL_UNSIGNED_BYTE;
cpp = 1;
break;
case GL_DEPTH_COMPONENT16:
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
irb->Base.DepthBits = 16;
irb->Base.DataType = GL_UNSIGNED_SHORT;
cpp = 2;
break;
case GL_DEPTH_COMPONENT24:
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
irb->Base.DepthBits = 24;
irb->Base.DataType = GL_UNSIGNED_INT;
cpp = 4;
break;
case GL_DEPTH24_STENCIL8_EXT:
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
irb->Base.DepthBits = 24;
irb->Base.StencilBits = 8;
irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
cpp = 4;
break;
default:
_mesa_problem(NULL, "Unexpected intFormat in intel_create_renderbuffer");
return NULL;
}
irb->Base.InternalFormat = intFormat;
/* intel-specific methods */
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_alloc_window_storage;
irb->Base.GetPointer = intel_get_pointer;
/* This sets the Get/PutRow/Value functions */
intel_set_span_functions(&irb->Base);
irb->pfMap = map;
irb->pfPitch = pitch;
#if 00
irb->region = intel_region_create_static(intel,
DRM_MM_TT,
offset,
map,
cpp,
width, height);
#endif
return irb;
}
/**
* Create a new renderbuffer object.
* Typically called via glBindRenderbufferEXT().
*/
static struct gl_renderbuffer *
intel_new_renderbuffer(GLcontext *ctx, GLuint name)
{
/*struct intel_context *intel = intel_context(ctx);*/
struct intel_renderbuffer *irb;
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
return NULL;
}
_mesa_init_renderbuffer(&irb->Base, name);
irb->Base.ClassID = INTEL_RB_CLASS;
/* intel-specific methods */
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
irb->Base.GetPointer = intel_get_pointer;
/* span routines set in alloc_storage function */
return &irb->Base;
}
/**
* Called via glBindFramebufferEXT().
*/
static void
intel_bind_framebuffer(GLcontext *ctx, GLenum target,
struct gl_framebuffer *fb)
{
/*
_mesa_debug(ctx, "%s %d\n", __FUNCTION__, fb->Name);
*/
/* XXX FBO: putting this flush here fixes a rendering offset bug.
* Not sure why this is needed when _mesa_BindFrameBuffer does
* a FLUSH_VERTICES().
*/
intelFlush(ctx);
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
intel_draw_buffer(ctx, fb);
/* Integer depth range depends on depth buffer bits */
ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
}
else {
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
}
}
/**
* Called via glFramebufferRenderbufferEXT().
*/
static void
intel_framebuffer_renderbuffer(GLcontext *ctx,
struct gl_framebuffer *fb,
GLenum attachment,
struct gl_renderbuffer *rb)
{
/*
_mesa_debug(ctx, "Intel FramebufferRenderbuffer %u %u\n",
fb->Name, rb ? rb->Name : 0);
*/
intelFlush(ctx);
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
intel_draw_buffer(ctx, fb);
}
/**
* When glFramebufferTexture[123]D is called this function sets up the
* gl_renderbuffer wrapp around the texture image.
* This will have the region info needed for hardware rendering.
*/
static struct intel_renderbuffer *
intel_wrap_texture(GLcontext *ctx, struct gl_texture_image *texImage)
{
const GLuint name = ~0; /* not significant, but distinct for debugging */
struct intel_renderbuffer *irb;
/* make an intel_renderbuffer to wrap the texture image */
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
return NULL;
}
_mesa_init_renderbuffer(&irb->Base, name);
irb->Base.ClassID = INTEL_RB_CLASS;
if (texImage->TexFormat == &_mesa_texformat_argb8888) {
irb->Base._ActualFormat = GL_RGBA8;
irb->Base._BaseFormat = GL_RGBA;
_mesa_debug(ctx, "Render to RGBA8 texture OK\n");
}
else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
irb->Base._ActualFormat = GL_RGB5;
irb->Base._BaseFormat = GL_RGB;
_mesa_debug(ctx, "Render to RGB5 texture OK\n");
}
else if (texImage->TexFormat == &_mesa_texformat_depth_component16) {
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
_mesa_debug(ctx, "Render to DEPTH16 texture OK\n");
}
else {
_mesa_debug(ctx, "Render to texture BAD FORMAT %d\n", texImage->TexFormat->MesaFormat);
_mesa_free(irb);
return NULL;
}
irb->Base.InternalFormat = irb->Base._ActualFormat;
irb->Base.Width = texImage->Width;
irb->Base.Height = texImage->Height;
irb->Base.DataType = GL_UNSIGNED_BYTE; /* FBO XXX fix */
irb->Base.RedBits = texImage->TexFormat->RedBits;
irb->Base.GreenBits = texImage->TexFormat->GreenBits;
irb->Base.BlueBits = texImage->TexFormat->BlueBits;
irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
irb->Base.DepthBits = texImage->TexFormat->DepthBits;
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_nop_alloc_storage;
intel_set_span_functions(&irb->Base);
irb->RenderToTexture = GL_TRUE;
return irb;
}
/**
* Called by glFramebufferTexture[123]DEXT() (and other places) to
* prepare for rendering into texture memory. This might be called
* many times to choose different texture levels, cube faces, etc
* before intel_finish_render_texture() is ever called.
*/
static void
intel_render_texture(GLcontext *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att)
{
struct gl_texture_image *newImage
= att->Texture->Image[att->CubeMapFace][att->TextureLevel];
struct intel_renderbuffer *irb
= intel_renderbuffer(att->Renderbuffer);
struct intel_texture_image *intel_image;
GLuint imageOffset;
(void) fb;
ASSERT(newImage);
if (!irb) {
irb = intel_wrap_texture(ctx, newImage);
if (irb) {
/* bind the wrapper to the attachment point */
att->Renderbuffer = &irb->Base;
}
else {
/* fallback to software rendering */
_mesa_render_texture(ctx, fb, att);
return;
}
}
/*
_mesa_debug(ctx, "Begin render texture tex=%u w=%d h=%d refcount=%d\n",
att->Texture->Name, newImage->Width, newImage->Height,
irb->Base.RefCount);
*/
/* point the renderbufer's region to the texture image region */
intel_image = intel_texture_image(newImage);
if (irb->region != intel_image->mt->region)
intel_region_reference(&irb->region, intel_image->mt->region);
/* compute offset of the particular 2D image within the texture region */
imageOffset = intel_miptree_image_offset(intel_image->mt,
att->CubeMapFace,
att->TextureLevel);
if (att->Texture->Target == GL_TEXTURE_3D) {
GLuint imgStride = intel_miptree_depth_image_stride(intel_image->mt,
att->CubeMapFace,
att->TextureLevel);
imageOffset += imgStride * att->Zoffset;
}
/* store that offset in the region */
intel_image->mt->region->draw_offset = imageOffset;
/* update drawing region, etc */
intel_draw_buffer(ctx, fb);
}
/**
* Called by Mesa when rendering to a texture is done.
*/
static void
intel_finish_render_texture(GLcontext *ctx,
struct gl_renderbuffer_attachment *att)
{
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb
= intel_renderbuffer(att->Renderbuffer);
/*
_mesa_debug(ctx, "End render texture (tid %u) tex %u\n",
_glthread_GetID(), att->Texture->Name);
*/
if (irb) {
/* just release the region */
intel_region_release(intel, &irb->region);
}
else if (att->Renderbuffer) {
/* software fallback */
_mesa_finish_render_texture(ctx, att);
/* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
}
}
/**
* Do one-time context initializations related to GL_EXT_framebuffer_object.
* Hook in device driver functions.
*/
void
intel_fbo_init( struct intel_context *intel )
{
intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
intel->ctx.Driver.RenderTexture = intel_render_texture;
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
}

View File

@@ -0,0 +1,75 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_FBO_H
#define INTEL_FBO_H
struct intel_context;
struct intel_region;
/**
* Intel renderbuffer, derived from gl_renderbuffer.
* Note: The PairedDepth and PairedStencil fields use renderbuffer IDs,
* not pointers because in some circumstances a deleted renderbuffer could
* result in a dangling pointer here.
*/
struct intel_renderbuffer {
struct gl_renderbuffer Base;
struct intel_region *region;
void *pfMap; /* possibly paged flipped map pointer */
GLuint pfPitch; /* possibly paged flipped pitch */
GLboolean RenderToTexture; /* RTT? */
GLuint PairedDepth; /**< only used if this is a depth renderbuffer */
GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */
};
extern struct intel_renderbuffer *
intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
int offset, int pitch, int cpp, void *map);
extern void
intel_fbo_init( struct intel_context *intel );
/* XXX make inline or macro */
extern struct intel_renderbuffer *
intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex);
/* XXX make inline or macro */
extern struct intel_region *
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex);
#endif /* INTEL_FBO_H */

View File

@@ -38,11 +38,13 @@
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_regions.h"
#include "drm.h"
#include "intel_bufmgr.h"
static int intelEmitIrqLocked( intelContextPtr intel )
int intelEmitIrqLocked( struct intel_context *intel )
{
drmI830IrqEmit ie;
int ret, seq = 0;
@@ -51,21 +53,21 @@ static int intelEmitIrqLocked( intelContextPtr intel )
(DRM_LOCK_HELD|intel->hHWContext));
ie.irq_seq = &seq;
ret = drmCommandWriteRead( intel->driFd, DRM_I830_IRQ_EMIT,
&ie, sizeof(ie) );
if ( ret ) {
fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret );
exit(1);
}
}
if (0)
fprintf(stderr, "%s --> %d\n", __FUNCTION__, seq );
return seq;
}
static void intelWaitIrq( intelContextPtr intel, int seq )
void intelWaitIrq( struct intel_context *intel, int seq )
{
drmI830IrqWait iw;
int ret;
@@ -81,527 +83,69 @@ static void intelWaitIrq( intelContextPtr intel, int seq )
if ( ret ) {
fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret );
if (0)
intel_dump_batchbuffer( intel->alloc.offset,
intel->alloc.ptr,
intel->alloc.size );
exit(1);
}
}
static void age_intel( intelContextPtr intel, int age )
{
GLuint i;
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
if (intel->CurrentTexObj[i])
intel->CurrentTexObj[i]->age = age;
}
void intel_dump_batchbuffer( long offset,
int *ptr,
int count )
{
int i;
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count);
for (i = 0; i < count/4; i += 4)
fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(unsigned int)offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]);
fprintf(stderr, "END BATCH\n\n\n");
}
void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock )
{
GLuint last_irq = intel->alloc.irq_emitted;
GLuint half = intel->alloc.size / 2;
GLuint buf = (intel->alloc.active_buf ^= 1);
intel->alloc.irq_emitted = intelEmitIrqLocked( intel );
if (last_irq) {
if (allow_unlock) UNLOCK_HARDWARE( intel );
intelWaitIrq( intel, last_irq );
if (allow_unlock) LOCK_HARDWARE( intel );
}
if (0)
fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf);
intel->batch.start_offset = intel->alloc.offset + buf * half;
intel->batch.ptr = (GLubyte *)intel->alloc.ptr + buf * half;
intel->batch.size = half - 8;
intel->batch.space = half - 8;
assert(intel->batch.space >= 0);
}
#define MI_BATCH_BUFFER_END (0xA<<23)
void intelFlushBatchLocked( intelContextPtr intel,
GLboolean ignore_cliprects,
GLboolean refill,
GLboolean allow_unlock)
void intel_batch_ioctl( struct intel_context *intel,
GLuint start_offset,
GLuint used,
GLboolean ignore_cliprects,
GLboolean allow_unlock)
{
drmI830BatchBuffer batch;
assert(intel->locked);
assert(used);
if (0)
fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n",
fprintf(stderr, "%s used %d offset %x..%x ignore_cliprects %d\n",
__FUNCTION__,
(intel->batch.size - intel->batch.space),
intel->batch.size,
intel->batch.start_offset,
intel->batch.start_offset +
(intel->batch.size - intel->batch.space),
refill);
used,
start_offset,
start_offset + used,
ignore_cliprects);
/* Throw away non-effective packets. Won't work once we have
* hardware contexts which would preserve statechanges beyond a
* single buffer.
*/
if (intel->numClipRects == 0 && !ignore_cliprects) {
/* Without this yeild, an application with no cliprects can hog
* the hardware. Without unlocking, the effect is much worse -
* effectively a lock-out of other contexts.
*/
if (allow_unlock) {
UNLOCK_HARDWARE( intel );
UNLOCK_HARDWARE(intel);
sched_yield();
LOCK_HARDWARE( intel );
LOCK_HARDWARE(intel);
}
/* Note that any state thought to have been emitted actually
* hasn't:
*/
intel->batch.ptr -= (intel->batch.size - intel->batch.space);
intel->batch.space = intel->batch.size;
intel->vtbl.lost_hardware( intel );
}
if (intel->batch.space != intel->batch.size) {
batch.start = intel->batch.start_offset;
batch.used = intel->batch.size - intel->batch.space;
batch.cliprects = intel->pClipRects;
batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
batch.DR1 = 0;
batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |
(((GLuint)intel->drawY) << 16));
if (intel->alloc.offset) {
if ((batch.used & 0x4) == 0) {
((int *)intel->batch.ptr)[0] = 0;
((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END;
batch.used += 0x8;
intel->batch.ptr += 0x8;
}
else {
((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END;
batch.used += 0x4;
intel->batch.ptr += 0x4;
}
}
if (0)
intel_dump_batchbuffer( batch.start,
(int *)(intel->batch.ptr - batch.used),
batch.used );
if (0)
fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
__FUNCTION__,
batch.start,
batch.start + batch.used,
batch.DR4, batch.num_cliprects);
intel->batch.start_offset += batch.used;
intel->batch.size -= batch.used;
if (intel->batch.size < 8) {
refill = GL_TRUE;
intel->batch.space = intel->batch.size = 0;
}
else {
intel->batch.size -= 8;
intel->batch.space = intel->batch.size;
}
assert(intel->batch.space >= 0);
assert(batch.start >= intel->alloc.offset);
assert(batch.start < intel->alloc.offset + intel->alloc.size);
assert(batch.start + batch.used > intel->alloc.offset);
assert(batch.start + batch.used <=
intel->alloc.offset + intel->alloc.size);
if (intel->alloc.offset) {
if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,
sizeof(batch))) {
fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
} else {
drmI830CmdBuffer cmd;
cmd.buf = (char *)intel->alloc.ptr + batch.start;
cmd.sz = batch.used;
cmd.DR1 = batch.DR1;
cmd.DR4 = batch.DR4;
cmd.num_cliprects = batch.num_cliprects;
cmd.cliprects = batch.cliprects;
if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd,
sizeof(cmd))) {
fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
}
age_intel(intel, intel->sarea->last_enqueue);
/* FIXME: use hardware contexts to avoid 'losing' hardware after
* each buffer flush.
*/
intel->vtbl.lost_hardware( intel );
}
if (refill)
intelRefillBatchLocked( intel, allow_unlock );
}
void intelFlushBatch( intelContextPtr intel, GLboolean refill )
{
if (intel->locked) {
intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE );
}
else {
LOCK_HARDWARE(intel);
intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE );
UNLOCK_HARDWARE(intel);
}
}
void intelWaitForIdle( intelContextPtr intel )
{
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
intel->vtbl.emit_flush( intel );
intelFlushBatch( intel, GL_TRUE );
/* Use an irq to wait for dma idle -- Need to track lost contexts
* to shortcircuit consecutive calls to this function:
*/
intelWaitIrq( intel, intel->alloc.irq_emitted );
intel->alloc.irq_emitted = 0;
}
void intelFlush( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
if (intel->Fallback)
_swrast_flush( ctx );
INTEL_FIREVERTICES( intel );
if (intel->batch.size != intel->batch.space)
intelFlushBatch( intel, GL_FALSE );
}
void intelFinish( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
intelFlush( ctx );
intelWaitForIdle( intel );
}
void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
GLbitfield tri_mask = 0;
GLbitfield blit_mask = 0;
GLbitfield swrast_mask = 0;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Take care of cliprects, which are handled differently for
* clears, etc.
*/
intelFlush( &intel->ctx );
if (mask & BUFFER_BIT_FRONT_LEFT) {
if (colorMask == ~0) {
blit_mask |= BUFFER_BIT_FRONT_LEFT;
}
else {
tri_mask |= BUFFER_BIT_FRONT_LEFT;
}
}
if (mask & BUFFER_BIT_BACK_LEFT) {
if (colorMask == ~0) {
blit_mask |= BUFFER_BIT_BACK_LEFT;
}
else {
tri_mask |= BUFFER_BIT_BACK_LEFT;
}
}
if (mask & BUFFER_BIT_DEPTH) {
blit_mask |= BUFFER_BIT_DEPTH;
}
if (mask & BUFFER_BIT_STENCIL) {
if (!intel->hw_stencil) {
swrast_mask |= BUFFER_BIT_STENCIL;
}
else if (ctx->Stencil.WriteMask[0] != 0xff) {
tri_mask |= BUFFER_BIT_STENCIL;
}
else {
blit_mask |= BUFFER_BIT_STENCIL;
}
}
swrast_mask |= (mask & BUFFER_BIT_ACCUM);
if (blit_mask)
intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
if (tri_mask)
intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch);
if (swrast_mask)
_swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
}
void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
{
int region_offset = 0;
drmI830MemAlloc alloc;
int ret;
if (0)
fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size);
alloc.region = I830_MEM_REGION_AGP;
alloc.alignment = 0;
alloc.size = size;
alloc.region_offset = &region_offset;
LOCK_HARDWARE(intel);
/* Make sure the global heap is initialized
*/
if (intel->texture_heaps[0])
driAgeTextures( intel->texture_heaps[0] );
ret = drmCommandWriteRead( intel->driFd,
DRM_I830_ALLOC,
&alloc, sizeof(alloc));
if (ret) {
fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret);
UNLOCK_HARDWARE(intel);
return NULL;
}
if (0)
fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size);
/* Need to propogate this information (agp memory in use) to our
* local texture lru. The kernel has already updated the global
* lru. An alternative would have been to allocate memory the
* usual way and then notify the kernel to pin the allocation.
*/
if (intel->texture_heaps[0])
driAgeTextures( intel->texture_heaps[0] );
UNLOCK_HARDWARE(intel);
return (void *)((char *)intel->intelScreen->tex.map + region_offset);
}
void intelFreeAGP( intelContextPtr intel, void *pointer )
{
int region_offset;
drmI830MemFree memfree;
int ret;
region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
if (region_offset < 0 ||
region_offset > intel->intelScreen->tex.size) {
fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
intel->intelScreen->tex.size);
return;
}
memfree.region = I830_MEM_REGION_AGP;
memfree.region_offset = region_offset;
ret = drmCommandWrite( intel->driFd,
DRM_I830_FREE,
&memfree, sizeof(memfree));
if (ret)
fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret);
}
/* This version of AllocateMemoryMESA allocates only agp memory, and
* only does so after the point at which the driver has been
* initialized.
*
* Theoretically a valid context isn't required. However, in this
* implementation, it is, as I'm using the hardware lock to protect
* the kernel data structures, and the current context to get the
* device fd.
*/
void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn,
GLsizei size, GLfloat readfreq,
GLfloat writefreq, GLfloat priority)
{
GET_CURRENT_CONTEXT(ctx);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
writefreq, priority);
if (getenv("INTEL_NO_ALLOC"))
return NULL;
if (!ctx || INTEL_CONTEXT(ctx) == 0)
return NULL;
return intelAllocateAGP( INTEL_CONTEXT(ctx), size );
}
/* Called via glXFreeMemoryMESA() */
void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
if (!ctx || INTEL_CONTEXT(ctx) == 0) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return;
}
intelFreeAGP( INTEL_CONTEXT(ctx), pointer );
}
/* Called via glXGetMemoryOffsetMESA()
*
* Returns offset of pointer from the start of agp aperture.
*/
GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn,
const GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
intelContextPtr intel;
if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return ~0;
}
if (!intelIsAgpMemory( intel, pointer, 0 ))
return ~0;
return intelAgpOffsetFromVirtual( intel, pointer );
}
GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
GLint size )
{
int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
int valid = (size >= 0 &&
offset >= 0 &&
offset + size < intel->intelScreen->tex.size);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid );
return valid;
}
GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer )
{
int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
if (offset < 0 || offset > intel->intelScreen->tex.size)
return ~0;
else
return intel->intelScreen->tex.offset + offset;
}
/* Flip the front & back buffes
*/
void intelPageFlip( const __DRIdrawablePrivate *dPriv )
{
#if 0
intelContextPtr intel;
int tmp, ret;
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (dPriv->pClipRects) {
*(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
intel->sarea->nbox = 1;
}
ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
if (ret) {
fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
UNLOCK_HARDWARE( intel );
batch.start = start_offset;
batch.used = used;
batch.cliprects = intel->pClipRects;
batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
batch.DR1 = 0;
batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |
(((GLuint)intel->drawY) << 16));
if (INTEL_DEBUG & DEBUG_DMA)
fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
__FUNCTION__,
batch.start,
batch.start + batch.used * 4,
batch.DR4, batch.num_cliprects);
#if 1
if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,
sizeof(batch))) {
fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
tmp = intel->sarea->last_enqueue;
intelRefillBatchLocked( intel );
UNLOCK_HARDWARE( intel );
intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
#endif
/* FIXME: use hardware contexts to avoid 'losing' hardware after
* each buffer flush.
*/
intel->vtbl.lost_hardware( intel );
}

View File

@@ -30,37 +30,14 @@
#include "intel_context.h"
extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock );
void intelWaitIrq( struct intel_context *intel, int seq );
int intelEmitIrqLocked( struct intel_context *intel );
extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch);
extern void intelPageFlip( const __DRIdrawablePrivate *dpriv );
extern void intelWaitForIdle( intelContextPtr intel );
extern void intelFlushBatch( intelContextPtr intel, GLboolean refill );
extern void intelFlushBatchLocked( intelContextPtr intel,
GLboolean ignore_cliprects,
GLboolean refill,
GLboolean allow_unlock);
extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock );
extern void intelFinish( GLcontext *ctx );
extern void intelFlush( GLcontext *ctx );
extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size );
extern void intelFreeAGP( intelContextPtr intel, void *pointer );
extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn,
GLsizei size, GLfloat readfreq,
GLfloat writefreq, GLfloat priority );
extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn,
GLvoid *pointer );
extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer );
extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
GLint size );
extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p );
void intel_batch_ioctl( struct intel_context *intel,
GLuint start_offset,
GLuint used,
GLboolean ignore_cliprects,
GLboolean allow_unlock);
#endif

View File

@@ -0,0 +1,300 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_bufmgr.h"
#include "enums.h"
static GLenum target_to_target( GLenum target )
{
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
return GL_TEXTURE_CUBE_MAP_ARB;
default:
return target;
}
}
struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
GLenum target,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
GLuint cpp,
GLboolean compressed)
{
GLboolean ok;
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
_mesa_lookup_enum_by_nr(internal_format),
first_level,
last_level);
mt->target = target_to_target(target);
mt->internal_format = internal_format;
mt->first_level = first_level;
mt->last_level = last_level;
mt->width0 = width0;
mt->height0 = height0;
mt->depth0 = depth0;
mt->cpp = cpp;
mt->compressed = compressed;
mt->refcount = 1;
switch (intel->intelScreen->deviceID) {
case PCI_CHIP_I945_G:
/* case PCI_CHIP_I945_GM: */
ok = i945_miptree_layout( mt );
break;
default:
/* All the i830 chips and the i915 use this layout:
*/
ok = i915_miptree_layout( mt );
break;
}
if (ok)
mt->region = intel_region_alloc( intel,
mt->cpp,
mt->pitch,
mt->total_height );
if (!mt->region) {
free(mt);
return NULL;
}
return mt;
}
void intel_miptree_reference( struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src )
{
src->refcount++;
*dst = src;
}
void intel_miptree_release( struct intel_context *intel,
struct intel_mipmap_tree **mt )
{
if (!*mt)
return;
DBG("%s %d\n", __FUNCTION__, (*mt)->refcount-1);
if (--(*mt)->refcount == 0) {
intel_region_release(intel, &((*mt)->region));
free(*mt);
}
*mt = NULL;
}
/* Can the image be pulled into a unified mipmap tree. This mirrors
* the completeness test in a lot of ways.
*
* Not sure whether I want to pass gl_texture_image here.
*/
GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
struct gl_texture_image *image,
GLuint face,
GLuint level )
{
DBG("%s %d %d/%d %d/%d\n", __FUNCTION__,
image->Border,
image->InternalFormat, mt->internal_format,
image->IsCompressed, mt->compressed);
/* Images with borders are never pulled into mipmap trees.
*/
if (image->Border)
return GL_FALSE;
if (image->InternalFormat != mt->internal_format ||
image->IsCompressed != mt->compressed)
return GL_FALSE;
DBG("%s: %d/%d %d/%d %d/%d\n", __FUNCTION__,
image->Width, mt->offset[face][level].width,
image->Height, mt->offset[face][level].height,
image->Depth, mt->offset[face][level].depth);
/* Test image dimensions against the base level image adjusted for
* minification. This will also catch images not present in the
* tree, changed targets, etc.
*/
if (image->Width != mt->offset[face][level].width ||
image->Height != mt->offset[face][level].height ||
image->Depth != mt->offset[face][level].depth)
return GL_FALSE;
DBG("%s: success\n", __FUNCTION__);
return GL_TRUE;
}
GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level)
{
return mt->offset[face][level].offset;
}
GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level)
{
return mt->offset[face][level].depth_image_stride;
}
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d)
{
mt->offset[face][level].offset = (x + y * mt->pitch) * mt->cpp;
mt->offset[face][level].width = w;
mt->offset[face][level].height = h;
mt->offset[face][level].depth = d;
}
/**
* Map a teximage in a mipmap tree.
* \param row_stride returns row stride in bytes
* \param image_stride returns image stride in bytes (for 3D textures).
* \return address of mapping
*/
GLubyte *intel_miptree_image_map(struct intel_context *intel,
struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint *row_stride,
GLuint *image_stride)
{
DBG("%s \n", __FUNCTION__);
if (row_stride)
*row_stride = mt->pitch * mt->cpp;
if (image_stride)
*image_stride = mt->offset[face][level].depth_image_stride;
return (intel_region_map(intel, mt->region) +
intel_miptree_image_offset(mt, face, level));
}
void intel_miptree_image_unmap(struct intel_context *intel,
struct intel_mipmap_tree *mt)
{
DBG("%s\n", __FUNCTION__);
intel_region_unmap(intel, mt->region);
}
/* Upload data for a particular image.
*/
void intel_miptree_image_data(struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face,
GLuint level,
void *src,
GLuint src_row_pitch,
GLuint src_image_pitch)
{
GLuint depth = dst->offset[face][level].depth;
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level);
GLuint i;
DBG("%s\n", __FUNCTION__);
for (i = 0; i < depth; i++) {
intel_region_data(intel,
dst->region, dst_offset,
0,
0,
src,
src_row_pitch,
0, 0, /* source x,y */
dst->offset[face][level].width,
dst->offset[face][level].height);
dst_offset += dst_image_stride;
src += src_image_pitch;
}
}
/* Copy mipmap image between trees
*/
void intel_miptree_image_copy( struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face, GLuint level,
struct intel_mipmap_tree *src )
{
GLuint width = src->offset[face][level].width;
GLuint height = src->offset[face][level].height;
GLuint depth = src->offset[face][level].depth;
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
GLuint src_offset = intel_miptree_image_offset(src, face, level);
GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level);
GLuint src_image_stride = intel_miptree_depth_image_stride(src, face, level);
GLuint i;
for (i = 0; i < depth; i++) {
intel_region_copy(intel,
dst->region, dst_offset,
0,
0,
src->region, src_offset,
0,
0,
width,
height);
dst_offset += dst_image_stride;
src_offset += src_image_stride;
}
}

View File

@@ -0,0 +1,183 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_MIPMAP_TREE_H
#define INTEL_MIPMAP_TREE_H
#include "intel_regions.h"
/* A layer on top of the intel_regions code which adds:
*
* - Code to size and layout a region to hold a set of mipmaps.
* - Query to determine if a new image fits in an existing tree.
* - More refcounting
* - maybe able to remove refcounting from intel_region?
* - ?
*
* The fixed mipmap layout of intel hardware where one offset
* specifies the position of all images in a mipmap hierachy
* complicates the implementation of GL texture image commands,
* compared to hardware where each image is specified with an
* independent offset.
*
* In an ideal world, each texture object would be associated with a
* single bufmgr buffer or 2d intel_region, and all the images within
* the texture object would slot into the tree as they arrive. The
* reality can be a little messier, as images can arrive from the user
* with sizes that don't fit in the existing tree, or in an order
* where the tree layout cannot be guessed immediately.
*
* This structure encodes an idealized mipmap tree. The GL image
* commands build these where possible, otherwise store the images in
* temporary system buffers.
*/
/**
* Describes the location of each texture image within a texture region.
*/
struct intel_mipmap_offset {
GLuint offset;
GLuint width;
GLuint height;
GLuint depth;
GLuint depth_image_stride;
};
struct intel_mipmap_tree {
/* Effectively the key:
*/
GLenum target;
GLenum internal_format;
GLuint first_level;
GLuint last_level;
GLuint width0, height0, depth0; /**< Level zero image dimensions */
GLuint cpp;
GLboolean compressed;
/* Derived from the above:
*/
GLuint pitch;
GLuint depth_pitch; /* per-image on i945? */
GLuint total_height;
struct intel_mipmap_offset offset[MAX_FACES][MAX_TEXTURE_LEVELS];
/* The data is held here:
*/
struct intel_region *region;
/* These are also refcounted:
*/
GLuint refcount;
};
struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
GLenum target,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
GLuint cpp,
GLboolean compressed);
void intel_miptree_reference( struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src );
void intel_miptree_release( struct intel_context *intel,
struct intel_mipmap_tree **mt );
/* Check if an image fits an existing mipmap tree layout
*/
GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
struct gl_texture_image *image,
GLuint face,
GLuint level );
/* Return a pointer to an image within a tree. Return image stride as
* well.
*/
GLubyte *intel_miptree_image_map( struct intel_context *intel,
struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint *row_stride,
GLuint *image_stride);
void intel_miptree_image_unmap( struct intel_context *intel,
struct intel_mipmap_tree *mt );
/* Return the linear offset of an image relative to the start of the
* tree:
*/
GLuint intel_miptree_image_offset( struct intel_mipmap_tree *mt,
GLuint face,
GLuint level );
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d);
GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level);
/* Upload an image into a tree
*/
void intel_miptree_image_data(struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face,
GLuint level,
void *src,
GLuint src_row_pitch,
GLuint src_image_pitch);
/* Copy an image between two trees
*/
void intel_miptree_image_copy( struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face, GLuint level,
struct intel_mipmap_tree *src );
/* i915_mipmap_tree.c:
*/
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt );
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt );
#endif

View File

@@ -1,6 +1,6 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -12,7 +12,7 @@
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* next paragraph) shall be included in all copies or substantial portionsalloc
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
@@ -25,465 +25,98 @@
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "state.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_pixel.h"
#include "intel_regions.h"
static GLboolean
check_color( const GLcontext *ctx, GLenum type, GLenum format,
const struct gl_pixelstore_attrib *packing,
const void *pixels, GLint sz, GLint pitch )
/**
* Check if any fragment operations are in effect which might effect
* glDraw/CopyPixels.
*/
GLboolean intel_check_blit_fragment_ops( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLuint cpp = intel->intelScreen->cpp;
if (ctx->NewState)
_mesa_update_state(ctx);
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* XXX Note: Scissor could be done with the blitter:
*/
return !(ctx->_ImageTransferState ||
ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits ||
ctx->FragmentProgram._Enabled);
}
if ( (pitch & 63) ||
ctx->_ImageTransferState ||
packing->SwapBytes ||
packing->LsbFirst) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
return GL_FALSE;
GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx )
{
if (ctx->NewState)
_mesa_update_state(ctx);
/* Some of _ImageTransferState (scale, bias) could be done with
* fragment programs on i915.
*/
return !(ctx->_ImageTransferState ||
ctx->Fog.Enabled || /* not done yet */
ctx->Texture._EnabledUnits ||
ctx->FragmentProgram._Enabled);
}
/* The intel_region struct doesn't really do enough to capture the
* format of the pixels in the region. For now this code assumes that
* the region is a display surface and hence is either ARGB8888 or
* RGB565.
* XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd
* know the buffer's pixel format.
*
* \param format as given to glDraw/ReadPixels
* \param type as given to glDraw/ReadPixels
*/
GLboolean intel_check_blit_format( struct intel_region *region,
GLenum format, GLenum type )
{
if (region->cpp == 4 &&
(type == GL_UNSIGNED_INT_8_8_8_8_REV ||
type == GL_UNSIGNED_BYTE) &&
format == GL_BGRA ) {
return GL_TRUE;
}
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&
cpp == 4 &&
format == GL_BGRA ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: passed 2\n", __FUNCTION__);
if (region->cpp == 2 &&
type == GL_UNSIGNED_SHORT_5_6_5_REV &&
format == GL_BGR ) {
return GL_TRUE;
}
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: failed\n", __FUNCTION__);
fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n",
__FUNCTION__, region->cpp,
_mesa_lookup_enum_by_nr(type),
_mesa_lookup_enum_by_nr(format));
return GL_FALSE;
}
static GLboolean
check_color_per_fragment_ops( const GLcontext *ctx )
{
int result;
result = (!( ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits
) &&
ctx->Current.RasterPosValid);
return result;
}
static GLboolean
clip_pixelrect( const GLcontext *ctx,
const GLframebuffer *buffer,
GLint *x, GLint *y,
GLsizei *width, GLsizei *height,
GLint *size )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
/* left clipping */
if (*x < buffer->_Xmin) {
*width -= (buffer->_Xmin - *x);
*x = buffer->_Xmin;
}
/* right clipping */
if (*x + *width > buffer->_Xmax)
*width -= (*x + *width - buffer->_Xmax - 1);
if (*width <= 0)
return GL_FALSE;
/* bottom clipping */
if (*y < buffer->_Ymin) {
*height -= (buffer->_Ymin - *y);
*y = buffer->_Ymin;
}
/* top clipping */
if (*y + *height > buffer->_Ymax)
*height -= (*y + *height - buffer->_Ymax - 1);
if (*height <= 0)
return GL_FALSE;
*size = ((*y + *height - 1) * intel->intelScreen->front.pitch +
(*x + *width - 1) * intel->intelScreen->cpp);
return GL_TRUE;
}
static GLboolean
intelTryReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLint size = 0;
GLint pitch = pack->RowLength ? pack->RowLength : width;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Only accelerate reading to agp buffers.
*/
if ( !intelIsAgpMemory(intel, pixels,
pitch * height * intel->intelScreen->cpp ) ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
return GL_FALSE;
}
/* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
* blitter:
*/
if (!pack->Invert) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
return GL_FALSE;
}
if (!check_color(ctx, type, format, pack, pixels, size, pitch))
return GL_FALSE;
switch ( intel->intelScreen->cpp ) {
case 4:
break;
default:
return GL_FALSE;
}
/* Although the blits go on the command buffer, need to do this and
* fire with lock held to guarentee cliprects and drawOffset are
* correct.
*
* This is an unusual situation however, as the code which flushes
* a full command buffer expects to be called unlocked. As a
* workaround, immediately flush the buffer on aquiring the lock.
*/
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
int src_offset = intel->drawOffset;
int src_pitch = intel->intelScreen->front.pitch;
int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
drm_clip_rect_t *box = dPriv->pClipRects;
int i;
if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
&size)) {
UNLOCK_HARDWARE( intel );
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s totally clipped -- nothing to do\n",
__FUNCTION__);
return GL_TRUE;
}
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
src_pitch, pitch);
for (i = 0 ; i < nbox ; i++)
{
GLint bx = box[i].x1;
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
if (bx < x) bw -= x - bx, bx = x;
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
if (by + bh > y + height) bh = y + height - by;
if (bw <= 0) continue;
if (bh <= 0) continue;
intelEmitCopyBlitLocked( intel,
intel->intelScreen->cpp,
src_pitch, src_offset,
pitch, dst_offset,
bx, by,
bx - x, by - y,
bw, bh );
}
}
UNLOCK_HARDWARE( intel );
intelFinish( &intel->ctx );
return GL_TRUE;
}
static void
intelReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack,
pixels))
_swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,
pixels);
}
static void do_draw_pix( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint pitch,
const void *pixels,
GLuint dest )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = intel->driDrawable;
drm_clip_rect_t *box = dPriv->pClipRects;
int nbox = dPriv->numClipRects;
int i;
int size;
int src_offset = intelAgpOffsetFromVirtual( intel, pixels);
int src_pitch = pitch;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (ctx->DrawBuffer)
{
y -= height; /* cope with pixel zoom */
if (!clip_pixelrect(ctx, ctx->DrawBuffer,
&x, &y, &width, &height,
&size)) {
UNLOCK_HARDWARE( intel );
return;
}
y = dPriv->h - y - height; /* convert from gl to hardware coords */
x += dPriv->x;
y += dPriv->y;
for (i = 0 ; i < nbox ; i++ )
{
GLint bx = box[i].x1;
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
if (bx < x) bw -= x - bx, bx = x;
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
if (by + bh > y + height) bh = y + height - by;
if (bw <= 0) continue;
if (bh <= 0) continue;
intelEmitCopyBlitLocked( intel,
intel->intelScreen->cpp,
src_pitch, src_offset,
intel->intelScreen->front.pitch,
intel->drawOffset,
bx - x, by - y,
bx, by,
bw, bh );
}
}
UNLOCK_HARDWARE( intel );
intelFinish( &intel->ctx );
}
static GLboolean
intelTryDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
GLuint dest;
GLuint cpp = intel->intelScreen->cpp;
GLint size = width * pitch * cpp;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
switch (format) {
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
dest = intel->drawOffset;
/* Planemask doesn't have full support in blits.
*/
if (!ctx->Color.ColorMask[RCOMP] ||
!ctx->Color.ColorMask[GCOMP] ||
!ctx->Color.ColorMask[BCOMP] ||
!ctx->Color.ColorMask[ACOMP]) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: planemask\n", __FUNCTION__);
return GL_FALSE;
}
/* Can't do conversions on agp reads/draws.
*/
if ( !intelIsAgpMemory( intel, pixels, size ) ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: not agp memory\n", __FUNCTION__);
return GL_FALSE;
}
if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
return GL_FALSE;
}
if (!check_color_per_fragment_ops(ctx)) {
return GL_FALSE;
}
if (ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != -1.0F)
return GL_FALSE;
break;
default:
return GL_FALSE;
}
if ( intelIsAgpMemory(intel, pixels, size) )
{
do_draw_pix( ctx, x, y, width, height, pitch, pixels,
dest );
return GL_TRUE;
}
else if (0)
{
/* Pixels is in regular memory -- get dma buffers and perform
* upload through them. No point doing this for regular uploads
* but once we remove some of the restrictions above (colormask,
* pixelformat conversion, zoom?, etc), this could be a win.
*/
}
else
return GL_FALSE;
}
static void
intelDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!intelTryDrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels ))
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
}
/**
* Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
* for the color buffer. Don't support zooming, pixel transfer, etc.
* We do support copying from one window to another, ala glXMakeCurrentRead.
*/
static void
intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy, GLsizei width, GLsizei height,
GLint destx, GLint desty, GLenum type )
{
#if 0
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
const SWcontext *swrast = SWRAST_CONTEXT( ctx );
XMesaDisplay *dpy = xmesa->xm_visual->display;
const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
const XMesaGC gc = xmesa->xm_draw_buffer->gc;
ASSERT(dpy);
ASSERT(gc);
if (drawBuffer && /* buffer != 0 means it's a Window or Pixmap */
readBuffer &&
type == GL_COLOR &&
(swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
ctx->Pixel.ZoomX == 1.0 && /* no zooming */
ctx->Pixel.ZoomY == 1.0) {
/* Note: we don't do any special clipping work here. We could,
* but X will do it for us.
*/
srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
XCopyArea(dpy, readBuffer, drawBuffer, gc,
srcx, srcy, width, height, destx, desty);
}
#else
_swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
#endif
}
void intelInitPixelFuncs( struct dd_function_table *functions )
{
/* Pixel path fallbacks.
*/
functions->Accum = _swrast_Accum;
functions->Bitmap = _swrast_Bitmap;
functions->CopyPixels = intelCopyPixels;
if (!getenv("INTEL_NO_BLITS")) {
functions->ReadPixels = intelReadPixels;
functions->DrawPixels = intelDrawPixels;
}
else {
functions->ReadPixels = _swrast_ReadPixels;
functions->DrawPixels = _swrast_DrawPixels;
}
functions->ReadPixels = intelReadPixels;
functions->DrawPixels = intelDrawPixels;
}

View File

@@ -0,0 +1,64 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_PIXEL_H
#define INTEL_PIXEL_H
#include "mtypes.h"
void intelInitPixelFuncs( struct dd_function_table *functions );
GLboolean intel_check_blit_fragment_ops( GLcontext *ctx );
GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx );
GLboolean intel_check_blit_format( struct intel_region *region,
GLenum format, GLenum type );
void intelReadPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels );
void intelDrawPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
void intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint destx, GLint desty,
GLenum type );
#endif

View File

@@ -0,0 +1,349 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "image.h"
#include "mtypes.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_buffers.h"
#include "intel_blit.h"
#include "intel_regions.h"
#include "intel_tris.h"
#include "intel_pixel.h"
#include "intel_bufmgr.h"
static struct intel_region *copypix_src_region( struct intel_context *intel,
GLenum type )
{
switch (type) {
case GL_COLOR:
return intel_readbuf_region( intel );
case GL_DEPTH:
/* Don't think this is really possible execpt at 16bpp, when we have no stencil.
*/
if (intel->depth_region &&
intel->depth_region->cpp == 2)
return intel->depth_region;
case GL_STENCIL:
/* Don't think this is really possible.
*/
break;
case GL_DEPTH_STENCIL_EXT:
/* Does it matter whether it is stencil/depth or depth/stencil?
*/
return intel->depth_region;
default:
break;
}
return NULL;
}
/* Doesn't work for overlapping regions. Could do a double copy or
* just fallback.
*/
static GLboolean do_texture_copypixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty,
GLenum type )
{
struct intel_context *intel = intel_context( ctx );
struct intel_region *dst = intel_drawbuf_region( intel );
struct intel_region *src = copypix_src_region(intel, type);
GLenum src_format;
GLenum src_type;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!src || !dst || type != GL_COLOR)
return GL_FALSE;
/* Can't handle overlapping regions. Don't have sufficient control
* over rasterization to pull it off in-place. Punt on these for
* now.
*
* XXX: do a copy to a temporary.
*/
{
drm_clip_rect_t src;
drm_clip_rect_t dst;
drm_clip_rect_t tmp;
src.x1 = srcx;
src.y1 = srcy;
src.x2 = srcx + width;
src.y2 = srcy + height;
dst.x1 = dstx;
dst.y1 = dsty;
dst.x1 = dstx + width * ctx->Pixel.ZoomX;
dst.y2 = dsty + height * ctx->Pixel.ZoomY;
if (intel_intersect_cliprects(&tmp, &src, &dst)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s: regions overlap\n", __FUNCTION__);
return GL_FALSE;
}
}
intelFlush( &intel->ctx );
intel->vtbl.install_meta_state(intel);
/* Is this true? Also will need to turn depth testing on according
* to state:
*/
intel->vtbl.meta_no_stencil_write(intel);
intel->vtbl.meta_no_depth_write(intel);
/* Set the 3d engine to draw into the destination region:
*/
intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
intel->vtbl.meta_import_pixel_state(intel);
if (src->cpp == 2) {
src_format = GL_RGB;
src_type = GL_UNSIGNED_SHORT_5_6_5;
}
else {
src_format = GL_BGRA;
src_type = GL_UNSIGNED_BYTE;
}
/* Set the frontbuffer up as a large rectangular texture.
*/
if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, 0,
src->pitch,
src->height,
src_format,
src_type )) {
intel->vtbl.leave_meta_state(intel);
return GL_FALSE;
}
intel->vtbl.meta_texture_blend_replace( intel );
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
srcx += dPriv->x;
srcy += dPriv->y;
/* Clip against the source region. This is the only source
* clipping we do. XXX: Just set the texcord wrap mode to clamp
* or similar.
*
*/
if (0) {
GLint orig_x = srcx;
GLint orig_y = srcy;
if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
&srcx, &srcy, &width, &height))
goto out;
dstx += srcx - orig_x;
dsty += (srcy - orig_y) * ctx->Pixel.ZoomY;
}
/* Just use the regular cliprect mechanism... Does this need to
* even hold the lock???
*/
intel_meta_draw_quad(intel,
dstx,
dstx + width * ctx->Pixel.ZoomX,
dPriv->h - (dsty + height * ctx->Pixel.ZoomY),
dPriv->h - (dsty),
0, /* XXX: what z value? */
0x00ff00ff,
srcx, srcx+width,
srcy, srcy+height);
out:
intel->vtbl.leave_meta_state(intel);
intel_batchbuffer_flush(intel->batch);
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
/**
* CopyPixels with the blitter. Don't support zooming, pixel transfer, etc.
*/
static GLboolean do_blit_copypixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty,
GLenum type )
{
struct intel_context *intel = intel_context( ctx );
struct intel_region *dst = intel_drawbuf_region( intel );
struct intel_region *src = copypix_src_region( intel, type );
/* Copypixels can be more than a straight copy. Ensure all the
* extra operations are disabled:
*/
if (!intel_check_blit_fragment_ops(ctx) ||
ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != 1.0F)
return GL_FALSE;
if (!src || !dst)
return GL_FALSE;
intelFlush( &intel->ctx );
intel->vtbl.render_start(intel);
intel->vtbl.emit_state(intel);
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
drm_clip_rect_t *box = dPriv->pClipRects;
drm_clip_rect_t dest_rect;
GLint nbox = dPriv->numClipRects;
GLint delta_x = 0;
GLint delta_y = 0;
GLuint i;
dsty = dPriv->h - dsty - height; /* convert from gl to hardware coords */
srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
dstx += dPriv->x;
dsty += dPriv->y;
srcx += dPriv->x;
srcy += dPriv->y;
/* Clip against the source region. This is the only source
* clipping we do. Dst is clipped with cliprects below.
*
* TODO: Scissor?
*/
{
delta_x = srcx - dstx;
delta_y = srcy - dsty;
if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
&srcx, &srcy, &width, &height))
goto out;
dstx = srcx - delta_x;
dsty = srcy - delta_y;
}
dest_rect.x1 = dstx;
dest_rect.y1 = dsty;
dest_rect.x2 = dstx + width;
dest_rect.y2 = dsty + height;
/* Could do slightly more clipping: Eg, take the intersection of
* the existing set of cliprects and those cliprects translated
* by delta_x, delta_y:
*
* This code will not overwrite other windows, but will
* introduce garbage when copying from obscured window regions.
*/
for (i = 0 ; i < nbox ; i++ )
{
drm_clip_rect_t rect;
if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
continue;
intelEmitCopyBlit( intel,
dst->cpp,
src->pitch, src->buffer, 0,
dst->pitch, dst->buffer, 0,
rect.x1 + delta_x,
rect.y1 + delta_y, /* srcx, srcy */
rect.x1,
rect.y1, /* dstx, dsty */
rect.x2 - rect.x1,
rect.y2 - rect.y1 );
}
out:
intel_batchbuffer_flush( intel->batch );
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
void intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint destx, GLint desty,
GLenum type )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (do_blit_copypixels( ctx, srcx, srcy, width, height, destx, desty, type))
return;
if (do_texture_copypixels( ctx, srcx, srcy, width, height, destx, desty, type))
return;
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("fallback to _swrast_CopyPixels\n");
_swrast_CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type);
}

View File

@@ -0,0 +1,365 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portionsalloc
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "image.h"
#include "mtypes.h"
#include "macros.h"
#include "bufferobj.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_buffers.h"
#include "intel_regions.h"
#include "intel_pixel.h"
#include "intel_buffer_objects.h"
#include "intel_tris.h"
#include "intel_bufmgr.h"
static GLboolean do_texture_drawpixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
struct intel_context *intel = intel_context( ctx );
struct intel_region *dst = intel_drawbuf_region( intel );
struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
GLuint src_offset;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
intelFlush( &intel->ctx );
intel->vtbl.render_start(intel);
intel->vtbl.emit_state(intel);
if (!dst)
return GL_FALSE;
if (src) {
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
format, type, pixels)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
return GL_TRUE;
}
}
else {
/* PBO only for now:
*/
/* _mesa_printf("%s - not PBO\n", __FUNCTION__); */
return GL_FALSE;
}
/* There are a couple of things we can't do yet, one of which is
* set the correct state for pixel operations when GL texturing is
* enabled. That's a pretty rare state and probably not worth the
* effort. A completely device-independent version of this may do
* more.
*
* Similarly, we make no attempt to merge metaops processing with
* an enabled fragment program, though it would certainly be
* possible.
*/
if (!intel_check_meta_tex_fragment_ops(ctx)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad GL fragment state for metaops texture\n", __FUNCTION__);
return GL_FALSE;
}
intel->vtbl.install_meta_state(intel);
/* Is this true? Also will need to turn depth testing on according
* to state:
*/
intel->vtbl.meta_no_stencil_write(intel);
intel->vtbl.meta_no_depth_write(intel);
/* Set the 3d engine to draw into the destination region:
*/
intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
intel->vtbl.meta_import_pixel_state(intel);
src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
format, type, 0, 0, 0);
/* Setup the pbo up as a rectangular texture, if possible.
*
* TODO: This is almost always possible if the i915 fragment
* program is adjusted to correctly swizzle the sampled colors.
* The major exception is any 24bit texture, like RGB888, for which
* there is no hardware support.
*/
if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, src_offset,
rowLength, height,
format, type )) {
intel->vtbl.leave_meta_state(intel);
return GL_FALSE;
}
intel->vtbl.meta_texture_blend_replace( intel );
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
GLint srcx, srcy;
GLint dstx, dsty;
dstx = x;
dsty = dPriv->h - (y + height);
srcx = 0; /* skiprows/pixels already done */
srcy = 0;
if (0) {
const GLint orig_x = dstx;
const GLint orig_y = dsty;
if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
&dstx, &dsty, &width, &height))
goto out;
srcx += dstx - orig_x;
srcy += dsty - orig_y;
}
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("draw %d,%d %dx%d\n", dstx,dsty,width,height);
/* Must use the regular cliprect mechanism in order to get the
* drawing origin set correctly. Otherwise scissor state is in
* incorrect coordinate space. Does this even need to hold the
* lock???
*/
intel_meta_draw_quad(intel,
dstx, dstx + width * ctx->Pixel.ZoomX,
dPriv->h - (y + height * ctx->Pixel.ZoomY),
dPriv->h - (y),
- ctx->Current.RasterPos[2] * .5,
0x00ff00ff,
srcx, srcx+width,
srcy+height, srcy);
out:
intel->vtbl.leave_meta_state(intel);
intel_batchbuffer_flush(intel->batch);
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
/* Pros:
* - no waiting for idle before updating framebuffer.
*
* Cons:
* - if upload is by memcpy, this may actually be slower than fallback path.
* - uploads the whole image even if destination is clipped
*
* Need to benchmark.
*
* Given the questions about performance, implement for pbo's only.
* This path is definitely a win if the pbo is already in agp. If it
* turns out otherwise, we can add the code necessary to upload client
* data to agp space before performing the blit. (Though it may turn
* out to be better/simpler just to use the texture engine).
*/
static GLboolean do_blit_drawpixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
struct intel_context *intel = intel_context(ctx);
struct intel_region *dest = intel_drawbuf_region(intel);
struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
GLuint src_offset;
GLuint rowLength;
GLuint fence = bmInitFence(intel->bm);
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s\n", __FUNCTION__);
if (!dest) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - no dest\n", __FUNCTION__);
return GL_FALSE;
}
if (src) {
/* This validation should be done by core mesa:
*/
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
format, type, pixels)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
return GL_TRUE;
}
}
else {
/* PBO only for now:
*/
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - not PBO\n", __FUNCTION__);
return GL_FALSE;
}
if (!intel_check_blit_format(dest, format, type)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad format for blit\n", __FUNCTION__);
return GL_FALSE;
}
if (!intel_check_meta_tex_fragment_ops(ctx)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad GL fragment state for meta tex\n", __FUNCTION__);
return GL_FALSE;
}
if (ctx->Pixel.ZoomX != 1.0F) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
return GL_FALSE;
}
if (unpack->RowLength > 0)
rowLength = unpack->RowLength;
else
rowLength = width;
if (ctx->Pixel.ZoomY == -1.0F) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
return GL_FALSE; /* later */
y -= height;
}
else if (ctx->Pixel.ZoomY == 1.0F) {
rowLength = -rowLength;
}
else {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
return GL_FALSE;
}
src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
format, type, 0, 0, 0);
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *box = dPriv->pClipRects;
drm_clip_rect_t rect;
drm_clip_rect_t dest_rect;
int i;
dest_rect.x1 = dPriv->x + x;
dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
dest_rect.x2 = dest_rect.x1 + width;
dest_rect.y2 = dest_rect.y1 + height;
for (i = 0 ; i < nbox ; i++ )
{
if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
continue;
intelEmitCopyBlit( intel,
dest->cpp,
rowLength,
intel_bufferobj_buffer(src), src_offset,
dest->pitch,
dest->buffer, 0,
rect.x1 - dest_rect.x1,
rect.y2 - dest_rect.y2,
rect.x1,
rect.y1,
rect.x2 - rect.x1,
rect.y2 - rect.y1 );
}
fence = intel_batchbuffer_flush( intel->batch );
}
UNLOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
bmFinishFence(intel->bm, fence);
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - DONE\n", __FUNCTION__);
return GL_TRUE;
}
void intelDrawPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
if (do_blit_drawpixels( ctx, x, y, width, height, format, type,
unpack, pixels ))
return;
if (do_texture_drawpixels( ctx, x, y, width, height, format, type,
unpack, pixels ))
return;
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
}

View File

@@ -0,0 +1,321 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "image.h"
#include "bufferobj.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_buffers.h"
#include "intel_regions.h"
#include "intel_pixel.h"
#include "intel_buffer_objects.h"
#include "intel_bufmgr.h"
/* For many applications, the new ability to pull the source buffers
* back out of the GTT and then do the packing/conversion operations
* in software will be as much of an improvement as trying to get the
* blitter and/or texture engine to do the work.
*
* This step is gated on private backbuffers.
*
* Obviously the frontbuffer can't be pulled back, so that is either
* an argument for blit/texture readpixels, or for blitting to a
* temporary and then pulling that back.
*
* When the destination is a pbo, however, it's not clear if it is
* ever going to be pulled to main memory (though the access param
* will be a good hint). So it sounds like we do want to be able to
* choose between blit/texture implementation on the gpu and pullback
* and cpu-based copying.
*
* Unless you can magically turn client memory into a PBO for the
* duration of this call, there will be a cpu-based copying step in
* any case.
*/
static GLboolean
do_texture_readpixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
struct intel_region *dest_region )
{
#if 0
struct intel_context *intel = intel_context(ctx);
intelScreenPrivate *screen = intel->intelScreen;
GLint pitch = pack->RowLength ? pack->RowLength : width;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int textureFormat;
GLenum glTextureFormat;
int destFormat, depthFormat, destPitch;
drm_clip_rect_t tmp;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( ctx->_ImageTransferState ||
pack->SwapBytes ||
pack->LsbFirst ||
!pack->Invert) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
return GL_FALSE;
}
intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel));
if (!intel->vtbl.meta_render_dest(intel,
dest_region,
type, format))
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: couldn't set dest %s/%s\n",
__FUNCTION__,
_mesa_lookup_enum_by_nr(type),
_mesa_lookup_enum_by_nr(format));
return GL_FALSE;
}
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects) {
intel->vtbl.install_meta_state(intel);
intel->vtbl.meta_no_depth_write(intel);
intel->vtbl.meta_no_stencil_write(intel);
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
return GL_TRUE;
}
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
/* Set the frontbuffer up as a large rectangular texture.
*/
intel->vtbl.meta_tex_rect_source( intel,
src_region,
textureFormat );
intel->vtbl.meta_texture_blend_replace( i830, glTextureFormat );
/* Set the 3d engine to draw into the destination region:
*/
intel->vtbl.meta_draw_region(intel, dest_region);
intel->vtbl.meta_draw_format(intel, destFormat, depthFormat ); /* ?? */
/* Draw a single quad, no cliprects:
*/
intel->vtbl.meta_disable_cliprects(intel);
intel->vtbl.draw_quad(intel,
0, width, 0, height,
0x00ff00ff,
x, x+width,
y, y+height );
intel->vtbl.leave_meta_state(intel);
}
UNLOCK_HARDWARE( intel );
intel_region_wait_fence( ctx, dest_region ); /* required by GL */
return GL_TRUE;
#endif
return GL_FALSE;
}
static GLboolean do_blit_readpixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
struct intel_context *intel = intel_context(ctx);
struct intel_region *src = intel_readbuf_region(intel);
struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
GLuint dst_offset;
GLuint rowLength;
GLuint fence = bmInitFence(intel->bm);
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s\n", __FUNCTION__);
if (!src)
return GL_FALSE;
if (dst) {
/* XXX This validation should be done by core mesa:
*/
if (!_mesa_validate_pbo_access(2, pack, width, height, 1,
format, type, pixels)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
return GL_TRUE;
}
}
else {
/* PBO only for now:
*/
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - not PBO\n", __FUNCTION__);
return GL_FALSE;
}
if (ctx->_ImageTransferState ||
!intel_check_blit_format(src, format, type)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad format for blit\n", __FUNCTION__);
return GL_FALSE;
}
if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s: bad packing params\n", __FUNCTION__);
return GL_FALSE;
}
if (pack->RowLength > 0)
rowLength = pack->RowLength;
else
rowLength = width;
if (pack->Invert) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__);
return GL_FALSE;
}
else {
rowLength = -rowLength;
}
/* XXX 64-bit cast? */
dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height,
format, type, 0, 0, 0);
/* Although the blits go on the command buffer, need to do this and
* fire with lock held to guarentee cliprects are correct.
*/
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *box = dPriv->pClipRects;
drm_clip_rect_t rect;
drm_clip_rect_t src_rect;
int i;
src_rect.x1 = dPriv->x + x;
src_rect.y1 = dPriv->y + dPriv->h - (y + height);
src_rect.x2 = src_rect.x1 + width;
src_rect.y2 = src_rect.y1 + height;
for (i = 0 ; i < nbox ; i++)
{
if (!intel_intersect_cliprects(&rect, &src_rect, &box[i]))
continue;
intelEmitCopyBlit( intel,
src->cpp,
src->pitch, src->buffer, 0,
rowLength,
intel_bufferobj_buffer(dst), dst_offset,
rect.x1,
rect.y1,
rect.x1 - src_rect.x1,
rect.y2 - src_rect.y2,
rect.x2 - rect.x1,
rect.y2 - rect.y1 );
}
fence = intel_batchbuffer_flush(intel->batch);
}
UNLOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
bmFinishFence(intel->bm, fence);
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - DONE\n", __FUNCTION__);
return GL_TRUE;
}
void
intelReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
intelFlush( ctx );
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
return;
if (do_texture_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
return;
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
_swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels);
}

View File

@@ -0,0 +1,264 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/* Provide additional functionality on top of bufmgr buffers:
* - 2d semantics and blit operations
* - refcounting of buffers for multiple images in a buffer.
* - refcounting of buffer mappings.
* - some logic for moving the buffers to the best memory pools for
* given operations.
*
* Most of this is to make it easier to implement the fixed-layout
* mipmap tree required by intel hardware in the face of GL's
* programming interface where each image can be specifed in random
* order and it isn't clear what layout the tree should have until the
* last moment.
*/
#include "intel_context.h"
#include "intel_regions.h"
#include "intel_blit.h"
#include "intel_bufmgr.h"
/* XXX: Thread safety?
*/
GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region)
{
DBG("%s\n", __FUNCTION__);
if (!region->map_refcount++) {
region->map = bmMapBuffer(intel->bm, region->buffer, 0);
}
return region->map;
}
void intel_region_unmap(struct intel_context *intel,
struct intel_region *region)
{
DBG("%s\n", __FUNCTION__);
if (!--region->map_refcount) {
bmUnmapBuffer(intel->bm, region->buffer);
region->map = NULL;
}
}
struct intel_region *intel_region_alloc( struct intel_context *intel,
GLuint cpp,
GLuint pitch,
GLuint height )
{
struct intel_region *region = calloc(sizeof(*region), 1);
DBG("%s\n", __FUNCTION__);
region->cpp = cpp;
region->pitch = pitch;
region->height = height; /* needed? */
region->refcount = 1;
bmGenBuffers(intel->bm, 1, &region->buffer, 0);
bmBufferData(intel->bm, region->buffer, pitch * cpp * height, NULL, 0);
return region;
}
void intel_region_reference( struct intel_region **dst,
struct intel_region *src)
{
assert(*dst == NULL);
if (src) {
src->refcount++;
*dst = src;
}
}
void intel_region_release( struct intel_context *intel,
struct intel_region **region )
{
if (!*region)
return;
DBG("%s %d\n", __FUNCTION__, (*region)->refcount-1);
ASSERT((*region)->refcount > 0);
(*region)->refcount--;
if ((*region)->refcount == 0) {
assert((*region)->map_refcount == 0);
bmDeleteBuffers(intel->bm, 1, &(*region)->buffer);
free(*region);
}
*region = NULL;
}
struct intel_region *intel_region_create_static( struct intel_context *intel,
GLuint mem_type,
GLuint offset,
void *virtual,
GLuint cpp,
GLuint pitch,
GLuint height )
{
struct intel_region *region = calloc(sizeof(*region), 1);
DBG("%s\n", __FUNCTION__);
region->cpp = cpp;
region->pitch = pitch;
region->height = height; /* needed? */
region->refcount = 1;
/*
* We use a "shared" buffer type to indicate buffers created and
* shared by others.
*/
bmGenBuffers(intel->bm, 1, &region->buffer, DRM_MM_TT | DRM_MM_SHARED);
bmSetShared(intel->bm, region->buffer, DRM_MM_TT, offset, virtual);
return region;
}
/*
* XXX Move this into core Mesa?
*/
static void _mesa_copy_rect( GLubyte *dst,
GLuint cpp,
GLuint dst_pitch,
GLuint dst_x,
GLuint dst_y,
GLuint width,
GLuint height,
GLubyte *src,
GLuint src_pitch,
GLuint src_x,
GLuint src_y )
{
GLuint i;
dst_pitch *= cpp;
src_pitch *= cpp;
dst += dst_x * cpp;
src += src_x * cpp;
dst += dst_y * dst_pitch;
src += src_y * dst_pitch;
width *= cpp;
if (width == dst_pitch &&
width == src_pitch)
memcpy(dst, src, height * width);
else {
for (i = 0; i < height; i++) {
memcpy(dst, src, width);
dst += dst_pitch;
src += src_pitch;
}
}
}
/* Upload data to a rectangular sub-region. Lots of choices how to do this:
*
* - memcpy by span to current destination
* - upload data as new buffer and blit
*
* Currently always memcpy.
*/
void intel_region_data(struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
void *src, GLuint src_pitch,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height)
{
DBG("%s\n", __FUNCTION__);
LOCK_HARDWARE(intel);
_mesa_copy_rect(intel_region_map(intel, dst) + dst_offset,
dst->cpp,
dst->pitch,
dstx, dsty,
width, height,
src,
src_pitch,
srcx, srcy);
intel_region_unmap(intel, dst);
UNLOCK_HARDWARE(intel);
}
/* Copy rectangular sub-regions. Need better logic about when to
* push buffers into AGP - will currently do so whenever possible.
*/
void intel_region_copy( struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
struct intel_region *src,
GLuint src_offset,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height )
{
DBG("%s\n", __FUNCTION__);
assert(src->cpp == dst->cpp);
intelEmitCopyBlit(intel,
dst->cpp,
src->pitch, src->buffer, src_offset,
dst->pitch, dst->buffer, dst_offset,
srcx, srcy,
dstx, dsty,
width, height);
}
/* Fill a rectangular sub-region. Need better logic about when to
* push buffers into AGP - will currently do so whenever possible.
*/
void intel_region_fill( struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
GLuint width, GLuint height,
GLuint color )
{
DBG("%s\n", __FUNCTION__);
intelEmitFillBlit(intel,
dst->cpp,
dst->pitch, dst->buffer, dst_offset,
dstx, dsty,
width, height,
color );
}

View File

@@ -0,0 +1,119 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_REGIONS_H
#define INTEL_REGIONS_H
#include "mtypes.h"
#include "intel_bufmgr.h" /* for DBG! */
struct intel_context;
/**
* A layer on top of the bufmgr buffers that adds a few useful things:
*
* - Refcounting for local buffer references.
* - Refcounting for buffer maps
* - Buffer dimensions - pitch and height.
* - Blitter commands for copying 2D regions between buffers. (really???)
*/
struct intel_region {
GLuint buffer; /**< buffer manager's buffer ID */
GLuint refcount; /**< Reference count for region */
GLuint cpp; /**< bytes per pixel */
GLuint pitch; /**< in pixels */
GLuint height; /**< in pixels */
GLubyte *map; /**< only non-NULL when region is actually mapped */
GLuint map_refcount; /**< Reference count for mapping */
GLuint draw_offset; /**< Offset of drawing address within the region */
};
/* Allocate a refcounted region. Pointers to regions should only be
* copied by calling intel_reference_region().
*/
struct intel_region *intel_region_alloc( struct intel_context *intel,
GLuint cpp,
GLuint pitch,
GLuint height );
void intel_region_reference( struct intel_region **dst,
struct intel_region *src );
void intel_region_release(struct intel_context *intel,
struct intel_region **ib );
struct intel_region *intel_region_create_static( struct intel_context *intel,
GLuint mem_type,
GLuint offset,
void *virtual,
GLuint cpp,
GLuint pitch,
GLuint height );
/* Map/unmap regions. This is refcounted also:
*/
GLubyte *intel_region_map(struct intel_context *intel,
struct intel_region *ib);
void intel_region_unmap(struct intel_context *intel,
struct intel_region *ib);
/* Upload data to a rectangular sub-region
*/
void intel_region_data(struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
void *src, GLuint src_stride,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height);
/* Copy rectangular sub-regions
*/
void intel_region_copy( struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
struct intel_region *src,
GLuint src_offset,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height );
/* Fill a rectangular sub-region
*/
void intel_region_fill( struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
GLuint width, GLuint height,
GLuint color );
#endif

View File

@@ -106,24 +106,29 @@ static const int scale_prim[GL_POLYGON+1] = {
};
static void intelDmaPrimitive( intelContextPtr intel, GLenum prim )
static void intelDmaPrimitive( struct intel_context *intel, GLenum prim )
{
if (0) fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
INTEL_FIREVERTICES(intel);
intel->vtbl.reduced_primitive_state( intel, reduced_prim[prim] );
intelStartInlinePrimitive( intel, hw_prim[prim] );
intelStartInlinePrimitive( intel, hw_prim[prim], INTEL_BATCH_CLIPRECTS );
}
#define LOCAL_VARS intelContextPtr intel = INTEL_CONTEXT(ctx)
#define LOCAL_VARS struct intel_context *intel = intel_context(ctx)
#define INIT( prim ) \
do { \
intelDmaPrimitive( intel, prim ); \
} while (0)
#define FLUSH() INTEL_FIREVERTICES( intel )
#define FLUSH() \
do { \
if (intel->prim.flush) \
intel->prim.flush(intel); \
} while (0)
#define GET_SUBSEQUENT_VB_MAX_VERTS() \
(((intel->alloc.size / 2) - 1500) / (intel->vertex_size*4))
((BATCH_SZ - 1500) / (intel->vertex_size*4))
#define GET_CURRENT_VB_MAX_VERTS() GET_SUBSEQUENT_VB_MAX_VERTS()
#define ALLOC_VERTS( nr ) \
@@ -142,7 +147,7 @@ do { \
/* Heuristic to choose between the two render paths:
*/
static GLboolean choose_render( intelContextPtr intel,
static GLboolean choose_render( struct intel_context *intel,
struct vertex_buffer *VB )
{
int vertsz = intel->vertex_size;
@@ -194,7 +199,7 @@ static GLboolean choose_render( intelContextPtr intel,
static GLboolean intel_run_render( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i;
@@ -225,6 +230,9 @@ static GLboolean intel_run_render( GLcontext *ctx,
}
tnl->Driver.Render.Finish( ctx );
if (intel->prim.flush)
intel->prim.flush(intel);
return GL_FALSE; /* finished the pipe */
}

View File

@@ -37,15 +37,16 @@
#include "intel_screen.h"
#include "intel_buffers.h"
#include "intel_tex.h"
#include "intel_span.h"
#include "intel_tris.h"
#include "intel_ioctl.h"
#include "intel_fbo.h"
#include "i830_dri.h"
PUBLIC const char __driConfigOptions[] =
DRI_CONF_BEGIN
DRI_CONF_SECTION_PERFORMANCE
@@ -104,14 +105,14 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
intelScreen->cpp = gDRIPriv->cpp;
switch (gDRIPriv->bitsPerPixel) {
case 15: intelScreen->fbFormat = DV_PF_555; break;
case 16: intelScreen->fbFormat = DV_PF_565; break;
case 32: intelScreen->fbFormat = DV_PF_8888; break;
default: exit(1); break;
}
intelScreen->front.pitch = gDRIPriv->fbStride;
intelScreen->front.offset = gDRIPriv->fbOffset;
intelScreen->front.map = sPriv->pFB;
intelScreen->front.map = (char *)sPriv->pFB;
intelScreen->back.offset = gDRIPriv->backOffset;
intelScreen->back.pitch = gDRIPriv->backPitch;
@@ -146,6 +147,12 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
return GL_FALSE;
}
#if 0
/*
* FIXME: Remove this code and its references.
*/
intelScreen->tex.offset = gDRIPriv->textureOffset;
intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity;
intelScreen->tex.handle = gDRIPriv->textures;
@@ -163,10 +170,17 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
sPriv->private = NULL;
return GL_FALSE;
}
#else
intelScreen->tex.offset = 0;
intelScreen->logTextureGranularity = 0;
intelScreen->tex.handle = 0;
intelScreen->tex.size = 0;
#endif
intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
if (1) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
intelScreen->drmMinor = sPriv->drmMinor;
@@ -202,13 +216,8 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
if (glx_enable_extension != NULL) {
(*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
(*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
}
sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA;
sPriv->psc->freeMemory = (void *) intelFreeMemoryMESA;
sPriv->psc->memoryOffset = (void *) intelGetMemoryOffsetMESA;
return GL_TRUE;
}
@@ -227,6 +236,9 @@ static void intelDestroyScreen(__DRIscreenPrivate *sPriv)
}
/**
* This is called when we need to set up GL rendering to a new X window.
*/
static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *mesaVis,
@@ -239,70 +251,71 @@ static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
} else {
GLboolean swStencil = (mesaVis->stencilBits > 0 &&
mesaVis->depthBits != 24);
GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
/* setup the hardware-based renderbuffers */
{
driRenderbuffer *frontRb
= driNewRenderbuffer(GL_RGBA,
driScrnPriv->pFB,
screen->cpp,
screen->front.offset, screen->front.pitch,
driDrawPriv);
intelSetSpanFunctions(frontRb, mesaVis);
struct intel_renderbuffer *frontRb
= intel_create_renderbuffer(rgbFormat,
screen->width, screen->height,
screen->front.offset,
screen->front.pitch,
screen->cpp,
driScrnPriv->pFB);
intel_set_span_functions(&frontRb->Base);
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
}
if (mesaVis->doubleBufferMode) {
driRenderbuffer *backRb
= driNewRenderbuffer(GL_RGBA,
screen->back.map,
screen->cpp,
screen->back.offset, screen->back.pitch,
driDrawPriv);
intelSetSpanFunctions(backRb, mesaVis);
struct intel_renderbuffer *backRb
= intel_create_renderbuffer(rgbFormat,
screen->width, screen->height,
screen->back.offset,
screen->back.pitch,
screen->cpp,
screen->back.map);
intel_set_span_functions(&backRb->Base);
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
}
if (mesaVis->depthBits == 16) {
driRenderbuffer *depthRb
= driNewRenderbuffer(GL_DEPTH_COMPONENT16,
screen->depth.map,
screen->cpp,
screen->depth.offset, screen->depth.pitch,
driDrawPriv);
intelSetSpanFunctions(depthRb, mesaVis);
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
/* combined depth/stencil buffer */
struct intel_renderbuffer *depthStencilRb
= intel_create_renderbuffer(
GL_DEPTH24_STENCIL8_EXT,
screen->width, screen->height,
screen->depth.offset,
screen->depth.pitch,
screen->cpp, /* 4! */
screen->depth.map);
intel_set_span_functions(&depthStencilRb->Base);
/* note: bind RB to two attachment points */
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base);
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base);
}
else if (mesaVis->depthBits == 24) {
driRenderbuffer *depthRb
= driNewRenderbuffer(GL_DEPTH_COMPONENT24,
screen->depth.map,
screen->cpp,
screen->depth.offset, screen->depth.pitch,
driDrawPriv);
intelSetSpanFunctions(depthRb, mesaVis);
else if (mesaVis->depthBits == 16) {
/* just 16-bit depth buffer, no hw stencil */
struct intel_renderbuffer *depthRb
= intel_create_renderbuffer(GL_DEPTH_COMPONENT16,
screen->width, screen->height,
screen->depth.offset,
screen->depth.pitch,
screen->cpp, /* 2! */
screen->depth.map);
intel_set_span_functions(&depthRb->Base);
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
}
if (mesaVis->stencilBits > 0 && !swStencil) {
driRenderbuffer *stencilRb
= driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
screen->depth.map,
screen->cpp,
screen->depth.offset, screen->depth.pitch,
driDrawPriv);
intelSetSpanFunctions(stencilRb, mesaVis);
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
}
/* now add any/all software-based renderbuffers we may need */
_mesa_add_soft_renderbuffers(fb,
GL_FALSE, /* color */
GL_FALSE, /* depth */
GL_FALSE, /* never sw color */
GL_FALSE, /* never sw depth */
swStencil,
mesaVis->accumRedBits > 0,
GL_FALSE, /* alpha */
GL_FALSE /* aux */);
GL_FALSE, /* never sw alpha */
GL_FALSE /* never sw aux */);
driDrawPriv->driverPrivate = (void *) fb;
return (driDrawPriv->driverPrivate != NULL);
@@ -338,6 +351,8 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
switch (intelScreen->deviceID) {
/* Don't deal with i830 until texture work complete:
*/
case PCI_CHIP_845_G:
case PCI_CHIP_I830_M:
case PCI_CHIP_I855_GM:

View File

@@ -32,6 +32,9 @@
#include "dri_util.h"
#include "xmlconfig.h"
/* XXX: change name or eliminate to avoid conflict with "struct
* intel_region"!!!
*/
typedef struct {
drm_handle_t handle;
drmSize size; /* region size in bytes */
@@ -54,7 +57,7 @@ typedef struct
int cpp; /* for front and back buffers */
int bitsPerPixel; /* unused */
int fbFormat;
int fbFormat; /* XXX FBO: this is obsolete - remove after i830 updates */
int logTextureGranularity;
@@ -84,7 +87,4 @@ intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv);
extern void
intelSwapBuffers( __DRIdrawablePrivate *dPriv);
#endif

View File

@@ -30,194 +30,340 @@
#include "mtypes.h"
#include "colormac.h"
#include "intel_fbo.h"
#include "intel_screen.h"
#include "intel_span.h"
#include "intel_regions.h"
#include "intel_ioctl.h"
#include "intel_tex.h"
#include "swrast/swrast.h"
/*
break intelWriteRGBASpan_ARGB8888
*/
#undef DBG
#define DBG 0
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
driRenderbuffer *drb = (driRenderbuffer *) rb; \
GLuint pitch = drb->pitch * drb->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *) drb->Base.Data + \
dPriv->x * drb->cpp + \
dPriv->y * pitch; \
GLushort p; \
(void) buf; (void) p
#define LOCAL_VARS \
struct intel_context *intel = intel_context(ctx); \
struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
const GLint yScale = irb->RenderToTexture ? 1 : -1; \
const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
GLubyte *buf = (GLubyte *) irb->pfMap \
+ (intel->drawY * irb->pfPitch + intel->drawX) * irb->region->cpp;\
GLuint p; \
assert(irb->pfMap);\
(void) p;
#define LOCAL_DEPTH_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
driRenderbuffer *drb = (driRenderbuffer *) rb; \
GLuint pitch = drb->pitch * drb->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *) drb->Base.Data + \
dPriv->x * drb->cpp + \
dPriv->y * pitch
/* XXX FBO: this is identical to the macro in spantmp2.h except we get
* the cliprect info from the context, not the driDrawable.
* Move this into spantmp2.h someday.
*/
#define HW_CLIPLOOP() \
do { \
int _nc = intel->numClipRects; \
while ( _nc-- ) { \
int minx = intel->pClipRects[_nc].x1 - intel->drawX; \
int miny = intel->pClipRects[_nc].y1 - intel->drawY; \
int maxx = intel->pClipRects[_nc].x2 - intel->drawX; \
int maxy = intel->pClipRects[_nc].y2 - intel->drawY;
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
#define INIT_MONO_PIXEL(p,color)\
p = INTEL_PACKCOLOR565(color[0],color[1],color[2])
#define Y_FLIP(_y) (height - _y - 1)
#define Y_FLIP(_y) ((_y) * yScale + yBias)
#define HW_LOCK()
#define HW_UNLOCK()
/* 16 bit, 565 rgb color spanline and pixel functions
/* 16 bit, RGB565 color spanline and pixel functions
*/
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = ( (((int)r & 0xf8) << 8) | \
(((int)g & 0xfc) << 3) | \
(((int)b & 0xf8) >> 3))
#define WRITE_PIXEL( _x, _y, p ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = p
#define SPANTMP_PIXEL_FMT GL_RGB
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
#define READ_RGBA( rgba, _x, _y ) \
do { \
GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \
rgba[0] = (((p >> 11) & 0x1f) * 255) / 31; \
rgba[1] = (((p >> 5) & 0x3f) * 255) / 63; \
rgba[2] = (((p >> 0) & 0x1f) * 255) / 31; \
rgba[3] = 255; \
} while(0)
#define TAG(x) intel##x##_RGB565
#define TAG2(x,y) intel##x##_RGB565##y
#define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 2)
#include "spantmp2.h"
#define TAG(x) intel##x##_565
#include "spantmp.h"
/* 15 bit, 555 rgb color spanline and pixel functions
/* 32 bit, ARGB8888 color spanline and pixel functions
*/
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = (((r & 0xf8) << 7) | \
((g & 0xf8) << 3) | \
((b & 0xf8) >> 3))
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
#define WRITE_PIXEL( _x, _y, p ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = p
#define TAG(x) intel##x##_ARGB8888
#define TAG2(x,y) intel##x##_ARGB8888##y
#define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 4)
#include "spantmp2.h"
#define READ_RGBA( rgba, _x, _y ) \
do { \
GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \
rgba[0] = (p >> 7) & 0xf8; \
rgba[1] = (p >> 3) & 0xf8; \
rgba[2] = (p << 3) & 0xf8; \
rgba[3] = 255; \
} while(0)
#define TAG(x) intel##x##_555
#include "spantmp.h"
#define LOCAL_DEPTH_VARS \
struct intel_context *intel = intel_context(ctx); \
struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
const GLuint pitch = irb->pfPitch/***XXX region->pitch*/; /* in pixels */ \
const GLint yScale = irb->RenderToTexture ? 1 : -1; \
const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
char *buf = (char *) irb->pfMap/*XXX use region->map*/ + \
(intel->drawY * pitch + intel->drawX) * irb->region->cpp;
/* 16 bit depthbuffer functions.
*/
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
/**
** 16-bit depthbuffer functions.
**/
#define WRITE_DEPTH( _x, _y, d ) \
*(GLushort *)(buf + (_x)*2 + (_y)*pitch) = d;
((GLushort *)buf)[(_x) + (_y) * pitch] = d;
#define READ_DEPTH( d, _x, _y ) \
d = *(GLushort *)(buf + (_x)*2 + (_y)*pitch);
d = ((GLushort *)buf)[(_x) + (_y) * pitch];
#define TAG(x) intel##x##_z16
#include "depthtmp.h"
#undef LOCAL_VARS
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
driRenderbuffer *drb = (driRenderbuffer *) rb; \
GLuint pitch = drb->pitch * drb->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *)drb->Base.Data + \
dPriv->x * drb->cpp + \
dPriv->y * pitch; \
GLuint p; \
(void) buf; (void) p
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p,color)\
p = INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3])
/* 32 bit, 8888 argb color spanline and pixel functions
*/
#define WRITE_RGBA(_x, _y, r, g, b, a) \
*(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) | \
(g << 8) | \
(b << 0) | \
(a << 24) )
#define WRITE_PIXEL(_x, _y, p) \
*(GLuint *)(buf + _x*4 + _y*pitch) = p
#define READ_RGBA(rgba, _x, _y) \
do { \
GLuint p = *(GLuint *)(buf + _x*4 + _y*pitch); \
rgba[0] = (p >> 16) & 0xff; \
rgba[1] = (p >> 8) & 0xff; \
rgba[2] = (p >> 0) & 0xff; \
rgba[3] = (p >> 24) & 0xff; \
} while (0)
#define TAG(x) intel##x##_8888
#include "spantmp.h"
/* 24/8 bit interleaved depth/stencil functions
*/
#define WRITE_DEPTH( _x, _y, d ) { \
GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
tmp &= 0xff000000; \
tmp |= (d) & 0xffffff; \
*(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
/**
** 24/8-bit interleaved depth/stencil functions
** Note: we're actually reading back combined depth+stencil values.
** The wrappers in main/depthstencil.c are used to extract the depth
** and stencil values.
**/
/* Change ZZZS -> SZZZ */
#define WRITE_DEPTH( _x, _y, d ) { \
GLuint tmp = ((d) >> 8) | ((d) << 24); \
((GLuint *)buf)[(_x) + (_y) * pitch] = tmp; \
}
#define READ_DEPTH( d, _x, _y ) \
d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) & 0xffffff;
/* Change SZZZ -> ZZZS */
#define READ_DEPTH( d, _x, _y ) { \
GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch]; \
d = (tmp << 8) | (tmp >> 24); \
}
#define TAG(x) intel##x##_z24_s8
#include "depthtmp.h"
#define WRITE_STENCIL( _x, _y, d ) { \
GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
tmp &= 0xffffff; \
tmp |= ((d)<<24); \
*(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
/**
** 8-bit stencil function (XXX FBO: This is obsolete)
**/
#define WRITE_STENCIL( _x, _y, d ) { \
GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch]; \
tmp &= 0xffffff; \
tmp |= ((d) << 24); \
((GLuint *) buf)[(_x) + (_y) * pitch] = tmp; \
}
#define READ_STENCIL( d, _x, _y ) \
d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) >> 24;
#define READ_STENCIL( d, _x, _y ) \
d = ((GLuint *)buf)[(_x) + (_y) * pitch] >> 24;
#define TAG(x) intel##x##_z24_s8
#include "stenciltmp.h"
/* Move locking out to get reasonable span performance.
/**
* Map or unmap all the renderbuffers which we may need during
* software rendering.
* XXX in the future, we could probably convey extra information to
* reduce the number of mappings needed. I.e. if doing a glReadPixels
* from the depth buffer, we really only need one mapping.
*
* XXX Rewrite this function someday.
* We can probably just loop over all the renderbuffer attachments,
* map/unmap all of them, and not worry about the _ColorDrawBuffers
* _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields.
*/
static void
intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
{
GLcontext *ctx = &intel->ctx;
GLuint i, j;
struct intel_renderbuffer *irb;
/* color draw buffers */
for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers[i]; j++) {
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i][j];
irb = intel_renderbuffer(rb);
if (irb) {
/* this is a user-created intel_renderbuffer */
if (irb->region) {
if (map)
intel_region_map(intel, irb->region);
else
intel_region_unmap(intel, irb->region);
}
irb->pfMap = irb->region->map;
irb->pfPitch = irb->region->pitch;
}
}
}
/* check for render to textures */
for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment + i;
struct gl_texture_object *tex = att->Texture;
if (tex) {
/* render to texture */
ASSERT(att->Renderbuffer);
if (map) {
struct gl_texture_image *texImg;
texImg = tex->Image[att->CubeMapFace][att->TextureLevel];
intel_tex_map_images(intel, intel_texture_object(tex));
}
else {
intel_tex_unmap_images(intel, intel_texture_object(tex));
}
}
}
/* color read buffers */
irb = intel_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
if (irb && irb->region) {
if (map)
intel_region_map(intel, irb->region);
else
intel_region_unmap(intel, irb->region);
irb->pfMap = irb->region->map;
irb->pfPitch = irb->region->pitch;
}
/* Account for front/back color page flipping.
* The span routines use the pfMap and pfPitch fields which will
* swap the front/back region map/pitch if we're page flipped.
* Do this after mapping, above, so the map field is valid.
*/
#if 0
if (map && ctx->DrawBuffer->Name == 0) {
struct intel_renderbuffer *irbFront
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_FRONT_LEFT);
struct intel_renderbuffer *irbBack
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_BACK_LEFT);
if (irbBack) {
/* double buffered */
if (intel->sarea->pf_current_page == 0) {
irbFront->pfMap = irbFront->region->map;
irbFront->pfPitch = irbFront->region->pitch;
irbBack->pfMap = irbBack->region->map;
irbBack->pfPitch = irbBack->region->pitch;
}
else {
irbFront->pfMap = irbBack->region->map;
irbFront->pfPitch = irbBack->region->pitch;
irbBack->pfMap = irbFront->region->map;
irbBack->pfPitch = irbFront->region->pitch;
}
}
}
#endif
/* depth buffer (Note wrapper!) */
if (ctx->DrawBuffer->_DepthBuffer) {
irb = intel_renderbuffer(ctx->DrawBuffer->_DepthBuffer->Wrapped);
if (irb && irb->region && irb->Base.Name != 0) {
if (map) {
intel_region_map(intel, irb->region);
irb->pfMap = irb->region->map;
irb->pfPitch = irb->region->pitch;
}
else {
intel_region_unmap(intel, irb->region);
irb->pfMap = NULL;
irb->pfPitch = 0;
}
}
}
/* stencil buffer (Note wrapper!) */
if (ctx->DrawBuffer->_StencilBuffer) {
irb = intel_renderbuffer(ctx->DrawBuffer->_StencilBuffer->Wrapped);
if (irb && irb->region && irb->Base.Name != 0) {
if (map) {
intel_region_map(intel, irb->region);
irb->pfMap = irb->region->map;
irb->pfPitch = irb->region->pitch;
}
else {
intel_region_unmap(intel, irb->region);
irb->pfMap = NULL;
irb->pfPitch = 0;
}
}
}
}
/**
* Prepare for softare rendering. Map current read/draw framebuffers'
* renderbuffes and all currently bound texture objects.
*
* Old note: Moved locking out to get reasonable span performance.
*/
void intelSpanRenderStart( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
GLuint i;
intelFlush(&intel->ctx);
LOCK_HARDWARE(intel);
intelWaitForIdle(intel);
#if 0
/* Just map the framebuffer and all textures. Bufmgr code will
* take care of waiting on the necessary fences:
*/
intel_region_map(intel, intel->front_region);
intel_region_map(intel, intel->back_region);
intel_region_map(intel, intel->depth_region);
#endif
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
intel_tex_map_images(intel, intel_texture_object(texObj));
}
}
intel_map_unmap_buffers(intel, GL_TRUE);
}
/**
* Called when done softare rendering. Unmap the buffers we mapped in
* the above function.
*/
void intelSpanRenderFinish( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
struct intel_context *intel = intel_context( ctx );
GLuint i;
_swrast_flush( ctx );
/* Now unmap the framebuffer:
*/
#if 0
intel_region_unmap(intel, intel->front_region);
intel_region_unmap(intel, intel->back_region);
intel_region_unmap(intel, intel->depth_region);
#endif
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
intel_tex_unmap_images(intel, intel_texture_object(texObj));
}
}
intel_map_unmap_buffers(intel, GL_FALSE);
UNLOCK_HARDWARE( intel );
}
void intelInitSpanFuncs( GLcontext *ctx )
{
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
@@ -227,32 +373,31 @@ void intelInitSpanFuncs( GLcontext *ctx )
/**
* Plug in the Get/Put routines for the given driRenderbuffer.
* Plug in appropriate span read/write functions for the given renderbuffer.
* These are used for the software fallbacks.
*/
void
intelSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
intel_set_span_functions(struct gl_renderbuffer *rb)
{
if (drb->Base.InternalFormat == GL_RGBA) {
if (vis->redBits == 5 && vis->greenBits == 5 && vis->blueBits == 5) {
intelInitPointers_555(&drb->Base);
}
else if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
intelInitPointers_565(&drb->Base);
}
else {
assert(vis->redBits == 8);
assert(vis->greenBits == 8);
assert(vis->blueBits == 8);
intelInitPointers_8888(&drb->Base);
}
if (rb->_ActualFormat == GL_RGB5) {
/* 565 RGB */
intelInitPointers_RGB565(rb);
}
else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
intelInitDepthPointers_z16(&drb->Base);
else if (rb->_ActualFormat == GL_RGBA8) {
/* 8888 RGBA */
intelInitPointers_ARGB8888(rb);
}
else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
intelInitDepthPointers_z24_s8(&drb->Base);
else if (rb->_ActualFormat == GL_DEPTH_COMPONENT16) {
intelInitDepthPointers_z16(rb);
}
else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
intelInitStencilPointers_z24_s8(&drb->Base);
else if (rb->_ActualFormat == GL_DEPTH_COMPONENT24 || /* XXX FBO remove */
rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
intelInitDepthPointers_z24_s8(rb);
}
else if (rb->_ActualFormat == GL_STENCIL_INDEX8_EXT) { /* XXX FBO remove */
intelInitStencilPointers_z24_s8(rb);
}
else {
_mesa_problem(NULL, "Unexpected _ActualFormat in intelSetSpanFunctions");
}
}

View File

@@ -28,14 +28,12 @@
#ifndef _INTEL_SPAN_H
#define _INTEL_SPAN_H
#include "drirenderbuffer.h"
extern void intelInitSpanFuncs( GLcontext *ctx );
extern void intelSpanRenderFinish( GLcontext *ctx );
extern void intelSpanRenderStart( GLcontext *ctx );
extern void
intelSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis);
intel_set_span_functions(struct gl_renderbuffer *rb);
#endif

View File

@@ -30,10 +30,13 @@
#include "context.h"
#include "macros.h"
#include "enums.h"
#include "colormac.h"
#include "dd.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_fbo.h"
#include "intel_regions.h"
#include "swrast/swrast.h"
int intel_translate_compare_func( GLenum func )
@@ -164,86 +167,67 @@ int intel_translate_logic_op( GLenum opcode )
}
}
static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *screen = intel->intelScreen;
int front = 0;
if (!ctx->DrawBuffer)
return;
switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
case BUFFER_BIT_FRONT_LEFT:
front = 1;
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
break;
case BUFFER_BIT_BACK_LEFT:
front = 0;
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
break;
default:
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
return;
}
if ( intel->sarea->pf_current_page == 1 )
front ^= 1;
intelSetFrontClipRects( intel );
if (front) {
intel->drawOffset = screen->front.offset;
} else {
intel->drawOffset = screen->back.offset;
}
intel->vtbl.set_draw_offset( intel, intel->drawOffset );
}
static void intelReadBuffer( GLcontext *ctx, GLenum mode )
{
/* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
}
static void intelClearColor(GLcontext *ctx, const GLfloat color[4])
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *screen = intel->intelScreen;
struct intel_context *intel = intel_context(ctx);
GLubyte clear[4];
CLAMPED_FLOAT_TO_UBYTE(intel->clear_red, color[0]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_green, color[1]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_blue, color[2]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_alpha, color[3]);
CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);
intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat,
intel->clear_red,
intel->clear_green,
intel->clear_blue,
intel->clear_alpha);
/* compute both 32 and 16-bit clear values */
intel->ClearColor8888 = INTEL_PACKCOLOR8888(clear[0], clear[1],
clear[2], clear[3]);
intel->ClearColor565 = INTEL_PACKCOLOR565(clear[0], clear[1], clear[2]);
}
/**
* Update the viewport transformation matrix. Depends on:
* - viewport pos/size
* - depthrange
* - window pos/size or FBO size
*/
static void intelCalcViewport( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
const GLfloat *v = ctx->Viewport._WindowMap.m;
const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
GLfloat *m = intel->ViewportMatrix.m;
GLint h = 0;
GLfloat yScale, yBias;
if (intel->driDrawable)
h = intel->driDrawable->h + SUBPIXEL_Y;
if (ctx->DrawBuffer->Name) {
/* User created FBO */
struct intel_renderbuffer *irb
= intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]);
if (irb && !irb->RenderToTexture) {
/* y=0=top */
yScale = -1.0;
yBias = irb->Base.Height;
}
else {
/* y=0=bottom */
yScale = 1.0;
yBias = 0.0;
}
}
else {
/* window buffer, y=0=top */
yScale = -1.0;
yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F;
}
/* See also intel_translate_vertex. SUBPIXEL adjustments can be done
* via state vars, too.
*/
m[MAT_SX] = v[MAT_SX];
m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
m[MAT_SY] = - v[MAT_SY];
m[MAT_TY] = - v[MAT_TY] + h;
m[MAT_SZ] = v[MAT_SZ] * intel->depth_scale;
m[MAT_TZ] = v[MAT_TZ] * intel->depth_scale;
m[MAT_SX] = v[MAT_SX];
m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
m[MAT_SY] = v[MAT_SY] * yScale;
m[MAT_TY] = v[MAT_TY] * yScale + yBias + SUBPIXEL_Y;
m[MAT_SZ] = v[MAT_SZ] * depthScale;
m[MAT_TZ] = v[MAT_TZ] * depthScale;
}
static void intelViewport( GLcontext *ctx,
@@ -263,18 +247,112 @@ static void intelDepthRange( GLcontext *ctx,
*/
static void intelRenderMode( GLcontext *ctx, GLenum mode )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
}
void intelInitStateFuncs( struct dd_function_table *functions )
{
functions->DrawBuffer = intelDrawBuffer;
functions->ReadBuffer = intelReadBuffer;
functions->RenderMode = intelRenderMode;
functions->Viewport = intelViewport;
functions->DepthRange = intelDepthRange;
functions->ClearColor = intelClearColor;
}
void intelInitState( GLcontext *ctx )
{
/* Mesa should do this for us:
*/
ctx->Driver.AlphaFunc( ctx,
ctx->Color.AlphaFunc,
ctx->Color.AlphaRef);
ctx->Driver.BlendColor( ctx,
ctx->Color.BlendColor );
ctx->Driver.BlendEquationSeparate( ctx,
ctx->Color.BlendEquationRGB,
ctx->Color.BlendEquationA);
ctx->Driver.BlendFuncSeparate( ctx,
ctx->Color.BlendSrcRGB,
ctx->Color.BlendDstRGB,
ctx->Color.BlendSrcA,
ctx->Color.BlendDstA);
ctx->Driver.ColorMask( ctx,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
ctx->Color.ColorMask[BCOMP],
ctx->Color.ColorMask[ACOMP]);
ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode );
ctx->Driver.DepthFunc( ctx, ctx->Depth.Func );
ctx->Driver.DepthMask( ctx, ctx->Depth.Mask );
ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag );
ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled );
ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled );
ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace );
{
GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
}
ctx->Driver.LineWidth( ctx, ctx->Line.Width );
ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp );
ctx->Driver.PointSize( ctx, ctx->Point.Size );
ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple );
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel );
ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT,
ctx->Stencil.Function[0],
ctx->Stencil.Ref[0],
ctx->Stencil.ValueMask[0] );
ctx->Driver.StencilFuncSeparate( ctx, GL_BACK,
ctx->Stencil.Function[1],
ctx->Stencil.Ref[1],
ctx->Stencil.ValueMask[1] );
ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
ctx->Driver.StencilOpSeparate( ctx, GL_FRONT,
ctx->Stencil.FailFunc[0],
ctx->Stencil.ZFailFunc[0],
ctx->Stencil.ZPassFunc[0]);
ctx->Driver.StencilOpSeparate( ctx, GL_BACK,
ctx->Stencil.FailFunc[1],
ctx->Stencil.ZFailFunc[1],
ctx->Stencil.ZPassFunc[1]);
/* XXX this isn't really needed */
ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
}

View File

@@ -1,830 +1,163 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "glheader.h"
#include "mtypes.h"
#include "imports.h"
#include "macros.h"
#include "simple_list.h"
#include "enums.h"
#include "image.h"
#include "texstore.h"
#include "texformat.h"
#include "teximage.h"
#include "texmem.h"
#include "texobj.h"
#include "swrast/swrast.h"
#include "mm.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "intel_ioctl.h"
static GLboolean
intelValidateClientStorage( intelContextPtr intel, GLenum target,
GLint internalFormat,
GLint srcWidth, GLint srcHeight,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
static GLboolean intelIsTextureResident(GLcontext *ctx,
struct gl_texture_object *texObj)
{
GLcontext *ctx = &intel->ctx;
int texelBytes;
if (0)
fprintf(stderr, "intformat %s format %s type %s\n",
_mesa_lookup_enum_by_nr( internalFormat ),
_mesa_lookup_enum_by_nr( format ),
_mesa_lookup_enum_by_nr( type ));
if (!ctx->Unpack.ClientStorage)
return 0;
if (ctx->_ImageTransferState ||
texImage->IsCompressed ||
texObj->GenerateMipmap)
return 0;
/* This list is incomplete
*/
switch ( internalFormat ) {
case GL_RGBA:
if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
texImage->TexFormat = &_mesa_texformat_argb8888;
texelBytes = 4;
}
else
return 0;
break;
case GL_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
texImage->TexFormat = &_mesa_texformat_rgb565;
texelBytes = 2;
}
else
return 0;
break;
case GL_YCBCR_MESA:
if ( format == GL_YCBCR_MESA &&
type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
texelBytes = 2;
}
else if ( format == GL_YCBCR_MESA &&
(type == GL_UNSIGNED_SHORT_8_8_APPLE ||
type == GL_UNSIGNED_BYTE)) {
texImage->TexFormat = &_mesa_texformat_ycbcr;
texelBytes = 2;
}
else
return 0;
break;
default:
return 0;
}
/* Could deal with these packing issues, but currently don't:
*/
if (packing->SkipPixels ||
packing->SkipRows ||
packing->SwapBytes ||
packing->LsbFirst) {
return 0;
}
{
GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
format, type);
if (0)
fprintf(stderr, "%s: srcRowStride %d/%x\n",
__FUNCTION__, srcRowStride, srcRowStride);
/* Could check this later in upload, pitch restrictions could be
* relaxed, but would need to store the image pitch somewhere,
* as packing details might change before image is uploaded:
*/
if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) ||
(srcRowStride & 63))
return 0;
/* Have validated that _mesa_transfer_teximage would be a straight
* memcpy at this point. NOTE: future calls to TexSubImage will
* overwrite the client data. This is explicitly mentioned in the
* extension spec.
*/
texImage->Data = (void *)pixels;
texImage->IsClientData = GL_TRUE;
texImage->RowStride = srcRowStride / texelBytes;
return 1;
}
}
static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
_mesa_store_teximage1d( ctx, target, level, internalFormat,
width, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images[0] |= (1 << level);
}
static void intelTexSubImage1D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, packing, texObj,
texImage);
#if 0
struct intel_context *intel = intel_context(ctx);
struct intel_texture_object *intelObj = intel_texture_object(texObj);
return
intelObj->mt &&
intelObj->mt->region &&
intel_is_region_resident(intel, intelObj->mt->region);
#endif
return 1;
}
/* Handles 2D, CUBE, RECT:
static struct gl_texture_image *intelNewTextureImage( GLcontext *ctx )
{
(void) ctx;
return (struct gl_texture_image *)CALLOC_STRUCT(intel_texture_image);
}
static struct gl_texture_object *intelNewTextureObject( GLcontext *ctx,
GLuint name,
GLenum target )
{
struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
_mesa_initialize_texture_object(&obj->base, name, target);
return &obj->base;
}
static void intelFreeTextureImageData( GLcontext *ctx,
struct gl_texture_image *texImage )
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
if (intelImage->mt) {
intel_miptree_release(intel, &intelImage->mt);
}
if (texImage->Data) {
free(texImage->Data);
texImage->Data = NULL;
}
}
#ifndef __x86_64__
static unsigned
fastrdtsc(void)
{
unsigned eax;
__asm__ volatile ("\t"
"pushl %%ebx\n\t"
"cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax)
:"0"(0)
:"ecx", "edx", "cc");
return eax;
}
#else
static unsigned
fastrdtsc(void)
{
unsigned eax;
__asm__ volatile ("\t"
"cpuid\n\t" ".byte 0x0f, 0x31\n\t" :"=a" (eax)
:"0"(0)
:"ecx", "edx", "ebx", "cc");
return eax;
}
#endif
static unsigned
time_diff(unsigned t, unsigned t2)
{
return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1));
}
/* The system memcpy (at least on ubuntu 5.10) has problems copying
* to agp (writecombined) memory from a source which isn't 64-byte
* aligned - there is a 4x performance falloff.
*
* The x86 __memcpy is immune to this but is slightly slower
* (10%-ish) than the system memcpy.
*
* The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
* isn't much faster than x86_memcpy for agp copies.
*
* TODO: switch dynamically.
*/
static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
static void *do_memcpy( void *dest, const void *src, size_t n )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
if ( (((unsigned)src) & 63) ||
(((unsigned)dest) & 63)) {
return __memcpy(dest, src, n);
}
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target,
internalFormat,
width, height,
format, type, pixels,
packing, texObj, texImage)) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
}
else {
_mesa_store_teximage2d( ctx, target, level, internalFormat,
width, height, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images[face] |= (1 << level);
}
}
static void intelTexSubImage2D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
if (texImage->IsClientData &&
(char *)pixels == (char *)texImage->Data +
((xoffset + yoffset * texImage->RowStride) *
texImage->TexFormat->TexelBytes)) {
/* Notification only - no upload required */
}
else {
assert( t ); /* this _should_ be true */
intelFlush( ctx );
driSwapOutTextureObject( t );
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
t->dirty_images[face] |= (1 << level);
}
}
static void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
_mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
height, border, imageSize, data, texObj, texImage);
t->dirty_images[face] |= (1 << level);
else
return memcpy(dest, src, n);
}
static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
static void *timed_memcpy( void *dest, const void *src, size_t n )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
void *ret;
unsigned t1, t2;
double rate;
if ( (((unsigned)src) & 63) ||
(((unsigned)dest) & 63))
_mesa_printf("Warning - non-aligned texture copy!\n");
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
t1 = fastrdtsc();
ret = do_memcpy(dest, src, n);
t2 = fastrdtsc();
assert( t ); /* this _should_ be true */
intelFlush( ctx );
driSwapOutTextureObject( t );
_mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, imageSize, data, texObj, texImage);
t->dirty_images[face] |= (1 << level);
rate = time_diff(t1, t2);
rate /= (double) n;
_mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate);
return ret;
}
static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
void intelInitTextureFuncs(struct dd_function_table * functions)
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
functions->ChooseTextureFormat = intelChooseTextureFormat;
functions->TexImage1D = intelTexImage1D;
functions->TexImage2D = intelTexImage2D;
functions->TexImage3D = intelTexImage3D;
functions->TexSubImage1D = intelTexSubImage1D;
functions->TexSubImage2D = intelTexSubImage2D;
functions->TexSubImage3D = intelTexSubImage3D;
functions->CopyTexImage1D = intelCopyTexImage1D;
functions->CopyTexImage2D = intelCopyTexImage2D;
functions->CopyTexSubImage1D = intelCopyTexSubImage1D;
functions->CopyTexSubImage2D = intelCopyTexSubImage2D;
functions->GetTexImage = intelGetTexImage;
functions->NewTextureObject = intelNewTextureObject;
functions->NewTextureImage = intelNewTextureImage;
functions->DeleteTexture = _mesa_delete_texture_object;
functions->FreeTexImageData = intelFreeTextureImageData;
functions->UpdateTexturePalette = 0;
functions->IsTextureResident = intelIsTextureResident;
assert(t);
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
_mesa_store_teximage3d(ctx, target, level, internalFormat,
width, height, depth, border,
format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void
intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert( t ); /* this _should_ be true */
driSwapOutTextureObject( t );
_mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
{
driTextureObject * t = (driTextureObject *) tObj->DriverData;
if ( t != NULL ) {
intelFlush( ctx );
driDestroyTextureObject( t );
}
/* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, tObj);
}
static const struct gl_texture_format *
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 &&
intel->intelScreen->tex.size > 4*1024*1024);
switch ( internalFormat ) {
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
return &_mesa_texformat_argb8888;
}
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
return &_mesa_texformat_argb4444;
}
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
return &_mesa_texformat_argb1555;
}
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
return &_mesa_texformat_rgb565;
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
return &_mesa_texformat_a8;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
return &_mesa_texformat_l8;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
return &_mesa_texformat_i8;
case GL_YCBCR_MESA:
if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
type == GL_UNSIGNED_BYTE)
return &_mesa_texformat_ycbcr;
else
return &_mesa_texformat_ycbcr_rev;
case GL_COMPRESSED_RGB_FXT1_3DFX:
return &_mesa_texformat_rgb_fxt1;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
return &_mesa_texformat_rgba_fxt1;
case GL_RGB_S3TC:
case GL_RGB4_S3TC:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
return &_mesa_texformat_rgb_dxt1;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return &_mesa_texformat_rgba_dxt1;
case GL_RGBA_S3TC:
case GL_RGBA4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
return &_mesa_texformat_rgba_dxt3;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return &_mesa_texformat_rgba_dxt5;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
return &_mesa_texformat_depth_component16;
default:
fprintf(stderr, "unexpected texture format %s in %s\n",
_mesa_lookup_enum_by_nr(internalFormat),
__FUNCTION__);
return NULL;
}
return NULL; /* never get here */
}
void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t)
{
unsigned i;
if ( intel == NULL )
return;
if ( t->age > intel->dirtyAge )
intel->dirtyAge = t->age;
for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
if ( t == intel->CurrentTexObj[ i ] )
intel->CurrentTexObj[ i ] = NULL;
}
}
/* Upload an image from mesa's internal copy. Image may be 1D, 2D or
* 3D. Cubemaps are expanded elsewhere.
*/
static void intelUploadTexImage( intelContextPtr intel,
intelTextureObjectPtr t,
const struct gl_texture_image *image,
const GLuint offset )
{
if (!image || !image->Data)
return;
if (image->Depth == 1 && image->IsClientData) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "Blit uploading\n");
/* Do it with a blit.
*/
intelEmitCopyBlitLocked( intel,
image->TexFormat->TexelBytes,
image->RowStride, /* ? */
intelGetMemoryOffsetMESA( NULL, 0, image->Data ),
t->Pitch / image->TexFormat->TexelBytes,
intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ),
0, 0,
0, 0,
image->Width,
image->Height);
}
else if (image->IsCompressed) {
GLuint row_len = image->Width * 2;
GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
GLubyte *src = (GLubyte *)image->Data;
GLuint j;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr,
"Upload image %dx%dx%d offset %xm row_len %x "
"pitch %x depth_pitch %x\n",
image->Width, image->Height, image->Depth, offset,
row_len, t->Pitch, t->depth_pitch);
switch (image->InternalFormat) {
case GL_COMPRESSED_RGB_FXT1_3DFX:
case GL_COMPRESSED_RGBA_FXT1_3DFX:
case GL_RGB_S3TC:
case GL_RGB4_S3TC:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
__memcpy(dst, src, row_len );
src += row_len;
}
break;
case GL_RGBA_S3TC:
case GL_RGBA4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
__memcpy(dst, src, (image->Width*4) );
src += image->Width*4;
}
break;
default:
fprintf(stderr,"Internal Compressed format not supported %d\n", image->InternalFormat);
break;
}
}
else {
GLuint row_len = image->Width * image->TexFormat->TexelBytes;
GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
GLubyte *src = (GLubyte *)image->Data;
GLuint d, j;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr,
"Upload image %dx%dx%d offset %xm row_len %x "
"pitch %x depth_pitch %x\n",
image->Width, image->Height, image->Depth, offset,
row_len, t->Pitch, t->depth_pitch);
if (row_len == t->Pitch) {
for (d = 0; d < image->Depth; d++) {
memcpy( dst, src, t->Pitch * image->Height );
dst += t->depth_pitch;
src += row_len * image->Height;
}
}
else {
for (d = 0 ; d < image->Depth ; d++) {
for (j = 0 ; j < image->Height ; j++) {
__memcpy(dst, src, row_len );
src += row_len;
dst += t->Pitch;
}
dst += t->depth_pitch - (t->Pitch * image->Height);
}
}
}
}
int intelUploadTexImages( intelContextPtr intel,
intelTextureObjectPtr t,
GLuint face)
{
const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image;
int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes;
/* Can we texture out of the existing client data? */
if ( numLevels == 1 &&
firstImage->IsClientData &&
(pitch & 3) == 0) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "AGP texturing from client memory\n");
t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data );
t->BufAddr = 0;
t->dirty = ~0;
return GL_TRUE;
}
else {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "Uploading client data to agp\n");
INTEL_FIREVERTICES( intel );
LOCK_HARDWARE( intel );
if ( t->base.memBlock == NULL ) {
int heap;
heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps,
(driTextureObject *) t );
if ( heap == -1 ) {
UNLOCK_HARDWARE( intel );
return GL_FALSE;
}
/* Set the base offset of the texture image */
t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs;
t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs;
t->dirty = ~0;
}
/* Let the world know we've used this memory recently.
*/
driUpdateTextureLRU( (driTextureObject *) t );
/* Upload any images that are new */
if (t->base.dirty_images[face]) {
int i;
intelWaitForIdle( intel );
for (i = 0 ; i < numLevels ; i++) {
int level = i + t->base.firstLevel;
if (t->base.dirty_images[face] & (1<<level)) {
const struct gl_texture_image *image = t->image[face][i].image;
GLuint offset = t->image[face][i].offset;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "upload level %d, offset %x\n",
level, offset);
intelUploadTexImage( intel, t, image, offset );
}
}
t->base.dirty_images[face] = 0;
intel->perf_boxes |= I830_BOX_TEXTURE_LOAD;
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
}
/**
* Allocate a new texture object.
* Called via ctx->Driver.NewTextureObject.
* Note: this function will be called during context creation to
* allocate the default texture objects.
* Note: we could use containment here to 'derive' the driver-specific
* texture object from the core mesa gl_texture_object. Not done at this time.
*/
static struct gl_texture_object *
intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
{
struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target);
INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj );
return obj;
}
void intelInitTextureFuncs( struct dd_function_table *functions )
{
functions->NewTextureObject = intelNewTextureObject;
functions->ChooseTextureFormat = intelChooseTextureFormat;
functions->TexImage1D = intelTexImage1D;
functions->TexImage2D = intelTexImage2D;
functions->TexImage3D = intelTexImage3D;
functions->TexSubImage1D = intelTexSubImage1D;
functions->TexSubImage2D = intelTexSubImage2D;
functions->TexSubImage3D = intelTexSubImage3D;
functions->CopyTexImage1D = _swrast_copy_teximage1d;
functions->CopyTexImage2D = _swrast_copy_teximage2d;
functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
functions->DeleteTexture = intelDeleteTexture;
functions->UpdateTexturePalette = NULL;
functions->IsTextureResident = driIsTextureResident;
functions->TestProxyTexImage = _mesa_test_proxy_teximage;
functions->DeleteTexture = intelDeleteTexture;
functions->CompressedTexImage2D = intelCompressedTexImage2D;
functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D;
if (INTEL_DEBUG & DEBUG_BUFMGR)
functions->TextureMemCpy = timed_memcpy;
else
functions->TextureMemCpy = do_memcpy;
}

View File

@@ -35,8 +35,102 @@
void intelInitTextureFuncs( struct dd_function_table *functions );
void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t );
int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t,
GLuint face );
const struct gl_texture_format *
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type );
void intelTexImage3D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexSubImage3D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexImage2D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexSubImage2D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexImage1D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexSubImage1D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width,
GLint border );
void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border );
void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset,
GLint x, GLint y, GLsizei width );
void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height );
void intelGetTexImage( GLcontext *ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid *pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage );
GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit );
void intel_tex_map_images( struct intel_context *intel,
struct intel_texture_object *intelObj );
void intel_tex_unmap_images( struct intel_context *intel,
struct intel_texture_object *intelObj );
#endif

View File

@@ -0,0 +1,296 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "mtypes.h"
#include "enums.h"
#include "image.h"
#include "teximage.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_buffers.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_fbo.h"
#include "intel_tex.h"
#include "intel_blit.h"
#include "intel_pixel.h"
#include "intel_bufmgr.h"
/**
* Get the intel_region which is the source for any glCopyTex[Sub]Image call.
*
* Do the best we can using the blitter. A future project is to use
* the texture engine and fragment programs for these copies.
*/
static const struct intel_region *
get_teximage_source(struct intel_context *intel, GLenum internalFormat)
{
struct intel_renderbuffer *irb;
if (0)
_mesa_printf("%s %s\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(internalFormat));
switch (internalFormat) {
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_ARB:
irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
if (irb && irb->region && irb->region->cpp == 2)
return irb->region;
return NULL;
case GL_DEPTH24_STENCIL8_EXT:
case GL_DEPTH_STENCIL_EXT:
irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
if (irb && irb->region && irb->region->cpp == 4)
return irb->region;
return NULL;
case GL_RGBA:
return intel_readbuf_region( intel );
case GL_RGB:
if (intel->intelScreen->cpp == 2)
return intel_readbuf_region( intel );
return NULL;
default:
return NULL;
}
}
static GLboolean do_copy_texsubimage( struct intel_context *intel,
struct intel_texture_image *intelImage,
GLenum internalFormat,
GLint dstx, GLint dsty,
GLint x, GLint y,
GLsizei width, GLsizei height )
{
GLcontext *ctx = &intel->ctx;
const struct intel_region *src = get_teximage_source(intel, internalFormat);
if (!intelImage->mt || !src)
return GL_FALSE;
intelFlush(ctx);
LOCK_HARDWARE(intel);
{
GLuint image_offset = intel_miptree_image_offset(intelImage->mt,
intelImage->face,
intelImage->level);
const GLint orig_x = x;
const GLint orig_y = y;
const struct gl_framebuffer *fb = ctx->DrawBuffer;
if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax,
&x, &y, &width, &height)) {
/* Update dst for clipped src. Need to also clip the source rect.
*/
dstx += x - orig_x;
dsty += y - orig_y;
if (ctx->ReadBuffer->Name == 0) {
/* reading from a window, adjust x, y */
__DRIdrawablePrivate *dPriv = intel->driDrawable;
GLuint window_y;
/* window_y = position of window on screen if y=0=bottom */
window_y = intel->intelScreen->height - (dPriv->y + dPriv->h);
y = window_y + y;
x += dPriv->x;
}
else {
/* reading from a FBO */
/* invert Y */
y = ctx->ReadBuffer->Height - y - 1;
}
/* A bit of fiddling to get the blitter to work with -ve
* pitches. But we get a nice inverted blit this way, so it's
* worth it:
*/
intelEmitCopyBlit( intel,
intelImage->mt->cpp,
-src->pitch,
src->buffer,
src->height * src->pitch * src->cpp,
intelImage->mt->pitch,
intelImage->mt->region->buffer,
image_offset,
x, y + height,
dstx, dsty,
width, height );
intel_batchbuffer_flush( intel->batch );
}
}
UNLOCK_HARDWARE(intel);
#if 0
/* GL_SGIS_generate_mipmap -- this can be accelerated now.
* XXX Add a ctx->Driver.GenerateMipmaps() function?
*/
if (level == texObj->BaseLevel &&
texObj->GenerateMipmap) {
intel_generate_mipmap(ctx, target,
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
#endif
return GL_TRUE;
}
void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width,
GLint border )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (border)
goto fail;
/* Setup or redefine the texture object, mipmap tree and texture
* image. Don't populate yet.
*/
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
width, border,
GL_RGBA, CHAN_TYPE, NULL,
&ctx->DefaultPacking, texObj, texImage);
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
0, 0,
x, y,
width, 1))
goto fail;
return;
fail:
_swrast_copy_teximage1d( ctx, target, level, internalFormat, x, y,
width, border );
}
void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (border)
goto fail;
/* Setup or redefine the texture object, mipmap tree and texture
* image. Don't populate yet.
*/
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
width, height, border,
GL_RGBA, CHAN_TYPE, NULL,
&ctx->DefaultPacking, texObj, texImage);
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
0, 0,
x, y,
width, height))
goto fail;
return;
fail:
_swrast_copy_teximage2d( ctx, target, level, internalFormat, x, y,
width, height, border );
}
void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset,
GLint x, GLint y, GLsizei width )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
GLenum internalFormat = texImage->InternalFormat;
/* XXX need to check <border> as in above function? */
/* Need to check texture is compatible with source format.
*/
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
xoffset, 0,
x, y, width, 1)) {
_swrast_copy_texsubimage1d( ctx, target, level,
xoffset, x, y, width );
}
}
void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
GLenum internalFormat = texImage->InternalFormat;
/* Need to check texture is compatible with source format.
*/
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
xoffset, yoffset,
x, y, width, height)) {
_swrast_copy_texsubimage2d( ctx, target, level,
xoffset, yoffset,
x, y, width, height );
}
}

View File

@@ -0,0 +1,148 @@
#include "intel_context.h"
#include "intel_tex.h"
#include "texformat.h"
#include "enums.h"
/* It works out that this function is fine for all the supported
* hardware. However, there is still a need to map the formats onto
* hardware descriptors.
*/
/* Note that the i915 can actually support many more formats than
* these if we take the step of simply swizzling the colors
* immediately after sampling...
*/
const struct gl_texture_format *
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
struct intel_context *intel = intel_context( ctx );
const GLboolean do32bpt = (intel->intelScreen->cpp == 4);
switch ( internalFormat ) {
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
return &_mesa_texformat_argb8888;
}
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
return &_mesa_texformat_argb4444;
}
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
return &_mesa_texformat_argb1555;
}
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
return &_mesa_texformat_rgb565;
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return &_mesa_texformat_argb8888;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
return &_mesa_texformat_a8;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
return &_mesa_texformat_l8;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
return &_mesa_texformat_i8;
case GL_YCBCR_MESA:
if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
type == GL_UNSIGNED_BYTE)
return &_mesa_texformat_ycbcr;
else
return &_mesa_texformat_ycbcr_rev;
case GL_COMPRESSED_RGB_FXT1_3DFX:
return &_mesa_texformat_rgb_fxt1;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
return &_mesa_texformat_rgba_fxt1;
case GL_RGB_S3TC:
case GL_RGB4_S3TC:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
return &_mesa_texformat_rgb_dxt1;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return &_mesa_texformat_rgba_dxt1;
case GL_RGBA_S3TC:
case GL_RGBA4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
return &_mesa_texformat_rgba_dxt3;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return &_mesa_texformat_rgba_dxt5;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
return &_mesa_texformat_depth_component16;
default:
fprintf(stderr, "unexpected texture format %s in %s\n",
_mesa_lookup_enum_by_nr(internalFormat),
__FUNCTION__);
return NULL;
}
return NULL; /* never get here */
}

View File

@@ -0,0 +1,444 @@
#include <stdlib.h>
#include <stdio.h>
#include "glheader.h"
#include "macros.h"
#include "mtypes.h"
#include "enums.h"
#include "colortab.h"
#include "convolve.h"
#include "context.h"
#include "simple_list.h"
#include "texcompress.h"
#include "texformat.h"
#include "texobj.h"
#include "texstore.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "intel_ioctl.h"
/* Functions to store texture images. Where possible, mipmap_tree's
* will be created or further instantiated with image data, otherwise
* images will be stored in malloc'd memory. A validation step is
* required to pull those images into a mipmap tree, or otherwise
* decide a fallback is required.
*/
static int logbase2(int n)
{
GLint i = 1;
GLint log2 = 0;
while (n > i) {
i *= 2;
log2++;
}
return log2;
}
/* Otherwise, store it in memory if (Border != 0) or (any dimension ==
* 1).
*
* Otherwise, if max_level >= level >= min_level, create tree with
* space for textures from min_level down to max_level.
*
* Otherwise, create tree with space for textures from (level
* 0)..(1x1). Consider pruning this tree at a validation if the
* saving is worth it.
*/
static void guess_and_alloc_mipmap_tree( struct intel_context *intel,
struct intel_texture_object *intelObj,
struct intel_texture_image *intelImage )
{
GLuint firstLevel;
GLuint lastLevel;
GLuint width = intelImage->base.Width;
GLuint height = intelImage->base.Height;
GLuint depth = intelImage->base.Depth;
GLuint l2width, l2height, l2depth;
GLuint i;
DBG("%s\n", __FUNCTION__);
if (intelImage->base.Border)
return;
if (intelImage->level > intelObj->base.BaseLevel &&
(intelImage->base.Width == 1 ||
(intelObj->base.Target != GL_TEXTURE_1D &&
intelImage->base.Height == 1) ||
(intelObj->base.Target == GL_TEXTURE_3D &&
intelImage->base.Depth == 1)))
return;
/* If this image disrespects BaseLevel, allocate from level zero.
* Usually BaseLevel == 0, so it's unlikely to happen.
*/
if (intelImage->level < intelObj->base.BaseLevel)
firstLevel = 0;
else
firstLevel = intelObj->base.BaseLevel;
/* Figure out image dimensions at start level.
*/
for (i = intelImage->level; i > firstLevel; i--) {
width <<= 1;
if (height != 1) height <<= 1;
if (depth != 1) depth <<= 1;
}
/* Guess a reasonable value for lastLevel. This is probably going
* to be wrong fairly often and might mean that we have to look at
* resizable buffers, or require that buffers implement lazy
* pagetable arrangements.
*/
if ((intelObj->base.MinFilter == GL_NEAREST ||
intelObj->base.MinFilter == GL_LINEAR) &&
intelImage->level == firstLevel) {
lastLevel = firstLevel;
}
else {
l2width = logbase2(width);
l2height = logbase2(height);
l2depth = logbase2(depth);
lastLevel = firstLevel + MAX2(MAX2(l2width,l2height),l2depth);
}
assert(!intelObj->mt);
intelObj->mt = intel_miptree_create( intel,
intelObj->base.Target,
intelImage->base.InternalFormat,
firstLevel,
lastLevel,
width,
height,
depth,
intelImage->base.TexFormat->TexelBytes,
intelImage->base.IsCompressed );
DBG("%s - success\n", __FUNCTION__);
}
static GLuint target_to_face( GLenum target )
{
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
return ((GLuint) target -
(GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
default:
return 0;
}
}
static void intelTexImage(GLcontext *ctx,
GLint dims,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_object *intelObj = intel_texture_object(texObj);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
GLint postConvWidth = width;
GLint postConvHeight = height;
GLint texelBytes, sizeInBytes;
GLuint dstRowStride;
GLuint dstImageStride;
DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level,
width, height, depth, border);
intelFlush(ctx);
intelImage->face = target_to_face( target );
intelImage->level = level;
if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
_mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
&postConvHeight);
}
/* choose the texture format */
texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat,
format, type);
assert(texImage->TexFormat);
switch (dims) {
case 1:
texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
break;
case 2:
texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
break;
case 3:
texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
break;
default:
assert(0);
break;
}
texelBytes = texImage->TexFormat->TexelBytes;
/* Minimum pitch of 32 bytes */
if (postConvWidth * texelBytes < 32) {
postConvWidth = 32 / texelBytes;
texImage->RowStride = postConvWidth;
}
assert(texImage->RowStride == postConvWidth);
/* Release the reference to a potentially orphaned buffer.
* Release any old malloced memory.
*/
if (intelImage->mt) {
intel_miptree_release(intel, &intelImage->mt);
assert(!texImage->Data);
}
else if (texImage->Data) {
free(texImage->Data);
}
/* If this is the only texture image in the tree, could call
* bmBufferData with NULL data to free the old block and avoid
* waiting on any outstanding fences.
*/
if (intelObj->mt &&
intelObj->mt->first_level == level &&
intelObj->mt->last_level == level &&
intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
!intel_miptree_match_image(intelObj->mt, &intelImage->base,
intelImage->face, intelImage->level)) {
DBG("release it\n");
intel_miptree_release(intel, &intelObj->mt);
assert(!intelObj->mt);
}
if (!intelObj->mt) {
guess_and_alloc_mipmap_tree(intel, intelObj, intelImage);
if (!intelObj->mt) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
_mesa_printf("guess_and_alloc_mipmap_tree: failed\n");
}
}
if (intelObj->mt &&
intelObj->mt != intelImage->mt &&
intel_miptree_match_image(intelObj->mt, &intelImage->base,
intelImage->face, intelImage->level)) {
if (intelImage->mt) {
intel_miptree_release(intel, &intelImage->mt);
}
intel_miptree_reference(&intelImage->mt, intelObj->mt);
assert(intelImage->mt);
}
if (!intelImage->mt) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
_mesa_printf("XXX: Image did not fit into tree - storing in local memory!\n");
}
/* intelCopyTexImage calls this function with pixels == NULL, with
* the expectation that the mipmap tree will be set up but nothing
* more will be done. This is where those calls return:
*/
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
format, type,
pixels, unpack, "glTexImage");
if (!pixels)
return;
LOCK_HARDWARE(intel);
if (intelImage->mt) {
texImage->Data = intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&dstRowStride,
&dstImageStride);
}
else {
/* Allocate regular memory and store the image there temporarily. */
if (texImage->IsCompressed) {
sizeInBytes = texImage->CompressedSize;
dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width);
dstImageStride = 0; /* ? */
assert(dims != 3);
}
else {
dstRowStride = postConvWidth * texelBytes;
dstImageStride = dstRowStride * postConvHeight;
sizeInBytes = depth * dstImageStride;
}
texImage->Data = malloc(sizeInBytes);
}
if (INTEL_DEBUG & DEBUG_TEXTURE)
_mesa_printf("Upload image %dx%dx%d row_len %x "
"pitch %x depth_pitch %x\n",
width, height, depth,
width * texelBytes, dstRowStride, dstImageStride);
/* Copy data. Would like to know when it's ok for us to eg. use
* the blitter to copy. Or, use the hardware to do the format
* conversion and copy:
*/
if (!texImage->TexFormat->StoreImage(ctx, dims,
texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data,
0, 0, 0, /* dstX/Y/Zoffset */
dstRowStride, dstImageStride,
width, height, depth,
format, type, pixels, unpack)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
}
_mesa_unmap_teximage_pbo(ctx, unpack);
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
texImage->Data = NULL;
}
UNLOCK_HARDWARE(intel);
#if 0
/* GL_SGIS_generate_mipmap -- this can be accelerated now.
*/
if (level == texObj->BaseLevel &&
texObj->GenerateMipmap) {
intel_generate_mipmap(ctx, target,
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
#endif
}
void intelTexImage3D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexImage( ctx, 3, target, level,
internalFormat, width, height, depth, border,
format, type, pixels,
unpack, texObj, texImage );
}
void intelTexImage2D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexImage( ctx, 2, target, level,
internalFormat, width, height, 1, border,
format, type, pixels,
unpack, texObj, texImage );
}
void intelTexImage1D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexImage( ctx, 1, target, level,
internalFormat, width, 1, 1, border,
format, type, pixels,
unpack, texObj, texImage );
}
/**
* Need to map texture image into memory before copying image data,
* then unmap it.
*/
void intelGetTexImage( GLcontext *ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid *pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
struct intel_context *intel = intel_context( ctx );
struct intel_texture_image *intelImage = intel_texture_image(texImage);
/* Map */
#ifdef ALL_IMAGES /* XXX Remove this, just for debug/test */
intel_tex_map_images(intel, intel_texture_object(texObj));
#else
/* XXX what if intelImage->mt is NULL? */
if (intelImage->mt) {
intelImage->base.Data =
intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&intelImage->base.RowStride,
&intelImage->base.ImageStride);
}
#endif
_mesa_get_teximage(ctx, target, level, format, type, pixels,
texObj, texImage);
/* Unmap */
#ifdef ALL_IMAGES
intel_tex_unmap_images(intel, intel_texture_object(texObj));
#else
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
intelImage->base.Data = NULL;
}
#endif
}

View File

@@ -0,0 +1,178 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "mtypes.h"
#include "texobj.h"
#include "texstore.h"
#include "enums.h"
#include "intel_context.h"
#include "intel_tex.h"
#include "intel_mipmap_tree.h"
static void intelTexSubimage (GLcontext *ctx,
GLint dims,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
GLuint dstImageStride;
GLuint dstRowStride;
DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level,
xoffset, yoffset,
width, height);
intelFlush(ctx);
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, type,
pixels, packing, "glTexSubImage2D");
if (!pixels)
return;
LOCK_HARDWARE(intel);
/* Map buffer if necessary. Need to lock to prevent other contexts
* from uploading the buffer under us.
*/
if (intelImage->mt)
texImage->Data = intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&dstRowStride,
&dstImageStride );
assert(dstRowStride);
if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data,
xoffset, yoffset, zoffset,
dstRowStride, dstImageStride,
width, height, depth,
format, type, pixels, packing)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
}
#if 0
/* GL_SGIS_generate_mipmap */
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target,
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
#endif
_mesa_unmap_teximage_pbo(ctx, packing);
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
texImage->Data = NULL;
}
UNLOCK_HARDWARE(intel);
}
void intelTexSubImage3D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 3,
target, level,
xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texObj,
texImage);
}
void intelTexSubImage2D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 2,
target, level,
xoffset, yoffset, 0,
width, height, 1,
format, type, pixels, packing, texObj,
texImage);
}
void intelTexSubImage1D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 1,
target, level,
xoffset, 0, 0,
width, 1, 1,
format, type, pixels, packing, texObj,
texImage);
}

View File

@@ -0,0 +1,247 @@
#include "mtypes.h"
#include "macros.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "intel_bufmgr.h"
/**
* Compute which mipmap levels that really need to be sent to the hardware.
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
*/
static void intel_calculate_first_last_level( struct intel_texture_object *intelObj )
{
struct gl_texture_object *tObj = &intelObj->base;
const struct gl_texture_image * const baseImage =
tObj->Image[0][tObj->BaseLevel];
/* These must be signed values. MinLod and MaxLod can be negative numbers,
* and having firstLevel and lastLevel as signed prevents the need for
* extra sign checks.
*/
int firstLevel;
int lastLevel;
/* Yes, this looks overly complicated, but it's all needed.
*/
switch (tObj->Target) {
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP:
if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
*/
firstLevel = lastLevel = tObj->BaseLevel;
}
else {
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
}
break;
case GL_TEXTURE_RECTANGLE_NV:
case GL_TEXTURE_4D_SGIS:
firstLevel = lastLevel = 0;
break;
default:
return;
}
/* save these values */
intelObj->firstLevel = firstLevel;
intelObj->lastLevel = lastLevel;
}
static void copy_image_data_to_tree( struct intel_context *intel,
struct intel_texture_object *intelObj,
struct intel_texture_image *intelImage )
{
if (intelImage->mt) {
/* Copy potentially with the blitter:
*/
intel_miptree_image_copy(intel,
intelObj->mt,
intelImage->face,
intelImage->level,
intelImage->mt);
intel_miptree_release(intel, &intelImage->mt);
}
else {
assert(intelImage->base.Data != NULL);
/* More straightforward upload.
*/
intel_miptree_image_data(intel,
intelObj->mt,
intelImage->face,
intelImage->level,
intelImage->base.Data,
intelImage->base.RowStride,
intelImage->base.RowStride * intelImage->base.Height);
free(intelImage->base.Data);
intelImage->base.Data = NULL;
}
intel_miptree_reference(&intelImage->mt, intelObj->mt);
}
/*
*/
GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit )
{
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
GLuint face, i;
GLuint nr_faces = 0;
struct intel_texture_image *firstImage;
/* We know/require this is true by now:
*/
assert(intelObj->base.Complete);
/* What levels must the tree include at a minimum?
*/
intel_calculate_first_last_level( intelObj );
firstImage = intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]);
/* Fallback case:
*/
if (firstImage->base.Border) {
if (intelObj->mt) {
intel_miptree_release(intel, &intelObj->mt);
}
return GL_FALSE;
}
/* If both firstImage and intelObj have a tree which can contain
* all active images, favour firstImage. Note that because of the
* completeness requirement, we know that the image dimensions
* will match.
*/
if (firstImage->mt &&
firstImage->mt != intelObj->mt &&
firstImage->mt->first_level <= intelObj->firstLevel &&
firstImage->mt->last_level >= intelObj->lastLevel) {
if (intelObj->mt)
intel_miptree_release(intel, &intelObj->mt);
intel_miptree_reference(&intelObj->mt, firstImage->mt);
}
/* Check tree can hold all active levels. Check tree matches
* target, imageFormat, etc.
*
* XXX: For some layouts (eg i945?), the test might have to be
* first_level == firstLevel, as the tree isn't valid except at the
* original start level. Hope to get around this by
* programming minLod, maxLod, baseLevel into the hardware and
* leaving the tree alone.
*/
if (intelObj->mt &&
((intelObj->mt->first_level > intelObj->firstLevel) ||
(intelObj->mt->last_level < intelObj->lastLevel) ||
(intelObj->mt->internal_format != firstImage->base.InternalFormat))) {
intel_miptree_release(intel, &intelObj->mt);
}
/* May need to create a new tree:
*/
if (!intelObj->mt) {
intelObj->mt = intel_miptree_create(intel,
intelObj->base.Target,
firstImage->base.InternalFormat,
intelObj->firstLevel,
intelObj->lastLevel,
firstImage->base.Width,
firstImage->base.Height,
firstImage->base.Depth,
firstImage->base.TexFormat->TexelBytes,
firstImage->base.IsCompressed);
}
/* Pull in any images not in the object's tree:
*/
nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
/* Need to import images in main memory or held in other trees.
*/
if (intelObj->mt != intelImage->mt) {
copy_image_data_to_tree(intel,
intelObj,
intelImage);
}
}
}
return GL_TRUE;
}
void intel_tex_map_images( struct intel_context *intel,
struct intel_texture_object *intelObj )
{
GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face, i;
DBG("%s\n", __FUNCTION__);
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
if (intelImage->mt) {
intelImage->base.Data =
intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&intelImage->base.RowStride,
&intelImage->base.ImageStride);
/* convert stride to texels, not bytes */
intelImage->base.RowStride /= intelImage->mt->cpp;
intelImage->base.ImageStride /= intelImage->mt->cpp;
}
}
}
}
void intel_tex_unmap_images( struct intel_context *intel,
struct intel_texture_object *intelObj )
{
GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face, i;
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
intelImage->base.Data = NULL;
}
}
}
}

View File

@@ -38,14 +38,95 @@
#include "tnl/t_vertex.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_tris.h"
#include "intel_batchbuffer.h"
#include "intel_reg.h"
#include "intel_span.h"
#include "intel_tex.h"
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim );
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
/*
*/
static void intel_flush_inline_primitive( struct intel_context *intel )
{
GLuint used = intel->batch->ptr - intel->prim.start_ptr;
assert(intel->prim.primitive != ~0);
if (used < 8)
goto do_discard;
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
intel->prim.primitive |
(used/4-2));
goto finished;
do_discard:
intel->batch->ptr -= used;
finished:
intel->prim.primitive = ~0;
intel->prim.start_ptr = 0;
intel->prim.flush = 0;
}
/* Emit a primitive referencing vertices in a vertex buffer.
*/
void intelStartInlinePrimitive( struct intel_context *intel,
GLuint prim,
GLuint batch_flags )
{
BATCH_LOCALS;
/* Emit a slot which will be filled with the inline primitive
* command later.
*/
BEGIN_BATCH(2, batch_flags);
OUT_BATCH( 0 );
intel->prim.start_ptr = intel->batch->ptr;
intel->prim.primitive = prim;
intel->prim.flush = intel_flush_inline_primitive;
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void intelWrapInlinePrimitive( struct intel_context *intel )
{
GLuint prim = intel->prim.primitive;
GLuint batchflags = intel->batch->flags;
intel_flush_inline_primitive(intel);
intel_batchbuffer_flush(intel->batch);
intel->vtbl.emit_state( intel );
intelStartInlinePrimitive( intel, prim, batchflags ); /* ??? */
}
GLuint *intelExtendInlinePrimitive( struct intel_context *intel,
GLuint dwords )
{
GLuint sz = dwords * sizeof(GLuint);
GLuint *ptr;
if (intel_batchbuffer_space(intel->batch) < sz)
intelWrapInlinePrimitive( intel );
ptr = (GLuint *)intel->batch->ptr;
intel->batch->ptr += sz;
return ptr;
}
/***********************************************************************
* Emit primitives as inline vertices *
***********************************************************************/
@@ -63,22 +144,18 @@ do { \
#else
#define COPY_DWORDS( j, vb, vertsize, v ) \
do { \
if (0) fprintf(stderr, "\n"); \
for ( j = 0 ; j < vertsize ; j++ ) { \
if (0) fprintf(stderr, " -- v(%d): %x/%f\n",j, \
((GLuint *)v)[j], \
((GLfloat *)v)[j]); \
vb[j] = ((GLuint *)v)[j]; \
} \
vb += vertsize; \
} while (0)
#endif
static void __inline__ intel_draw_quad( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2,
intelVertexPtr v3 )
static void intel_draw_quad( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2,
intelVertexPtr v3 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 6 * vertsize );
@@ -92,10 +169,10 @@ static void __inline__ intel_draw_quad( intelContextPtr intel,
COPY_DWORDS( j, vb, vertsize, v3 );
}
static void __inline__ intel_draw_triangle( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2 )
static void intel_draw_triangle( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 3 * vertsize );
@@ -107,9 +184,9 @@ static void __inline__ intel_draw_triangle( intelContextPtr intel,
}
static __inline__ void intel_draw_line( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1 )
static void intel_draw_line( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 2 * vertsize );
@@ -120,8 +197,8 @@ static __inline__ void intel_draw_line( intelContextPtr intel,
}
static __inline__ void intel_draw_point( intelContextPtr intel,
intelVertexPtr v0 )
static void intel_draw_point( struct intel_context *intel,
intelVertexPtr v0 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, vertsize );
@@ -140,7 +217,7 @@ static __inline__ void intel_draw_point( intelContextPtr intel,
* Fixup for ARB_point_parameters *
***********************************************************************/
static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
static void intel_atten_point( struct intel_context *intel, intelVertexPtr v0 )
{
GLcontext *ctx = &intel->ctx;
GLfloat psz[4], col[4], restore_psz, restore_alpha;
@@ -189,7 +266,7 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
static void intel_wpos_triangle( intelContextPtr intel,
static void intel_wpos_triangle( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2 )
@@ -205,7 +282,7 @@ static void intel_wpos_triangle( intelContextPtr intel,
}
static void intel_wpos_line( intelContextPtr intel,
static void intel_wpos_line( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1 )
{
@@ -219,7 +296,7 @@ static void intel_wpos_line( intelContextPtr intel,
}
static void intel_wpos_point( intelContextPtr intel,
static void intel_wpos_point( struct intel_context *intel,
intelVertexPtr v0 )
{
GLuint offset = intel->wpos_offset;
@@ -349,7 +426,7 @@ do { \
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
#define LOCAL_VARS(n) \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
struct intel_context *intel = intel_context(ctx); \
GLuint color[n], spec[n]; \
GLuint coloroffset = intel->coloroffset; \
GLboolean specoffset = intel->specoffset; \
@@ -481,7 +558,7 @@ static void init_rast_tab( void )
* primitives.
*/
static void
intel_fallback_tri( intelContextPtr intel,
intel_fallback_tri( struct intel_context *intel,
intelVertex *v0,
intelVertex *v1,
intelVertex *v2 )
@@ -491,6 +568,9 @@ intel_fallback_tri( intelContextPtr intel,
if (0)
fprintf(stderr, "\n%s\n", __FUNCTION__);
if (intel->prim.flush)
intel->prim.flush(intel);
_swsetup_Translate( ctx, v0, &v[0] );
_swsetup_Translate( ctx, v1, &v[1] );
@@ -502,7 +582,7 @@ intel_fallback_tri( intelContextPtr intel,
static void
intel_fallback_line( intelContextPtr intel,
intel_fallback_line( struct intel_context *intel,
intelVertex *v0,
intelVertex *v1 )
{
@@ -512,6 +592,9 @@ intel_fallback_line( intelContextPtr intel,
if (0)
fprintf(stderr, "\n%s\n", __FUNCTION__);
if (intel->prim.flush)
intel->prim.flush(intel);
_swsetup_Translate( ctx, v0, &v[0] );
_swsetup_Translate( ctx, v1, &v[1] );
intelSpanRenderStart( ctx );
@@ -520,24 +603,6 @@ intel_fallback_line( intelContextPtr intel,
}
static void
intel_fallback_point( intelContextPtr intel,
intelVertex *v0 )
{
GLcontext *ctx = &intel->ctx;
SWvertex v[1];
if (0)
fprintf(stderr, "\n%s\n", __FUNCTION__);
_swsetup_Translate( ctx, v0, &v[0] );
intelSpanRenderStart( ctx );
_swrast_Point( ctx, &v[0] );
intelSpanRenderFinish( ctx );
}
/**********************************************************************/
/* Render unclipped begin/end objects */
/**********************************************************************/
@@ -552,7 +617,7 @@ intel_fallback_point( intelContextPtr intel,
#define INIT(x) intelRenderPrimitive( ctx, x )
#undef LOCAL_VARS
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
struct intel_context *intel = intel_context(ctx); \
GLubyte *vertptr = (GLubyte *)intel->verts; \
const GLuint vertsize = intel->vertex_size; \
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
@@ -578,7 +643,7 @@ intel_fallback_point( intelContextPtr intel,
static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
GLuint n )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint prim = intel->render_primitive;
@@ -609,7 +674,7 @@ static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
GLuint n )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
struct intel_context *intel = intel_context( ctx );
const GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, (n-2) * 3 * vertsize );
GLubyte *vertptr = (GLubyte *)intel->verts;
@@ -630,17 +695,13 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
#define POINT_FALLBACK (0)
#define LINE_FALLBACK (DD_LINE_STIPPLE)
#define TRI_FALLBACK (0)
#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
DD_TRI_STIPPLE|DD_POINT_ATTEN)
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN)
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED)
void intelChooseRenderState(GLcontext *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
GLuint flags = ctx->_TriangleCaps;
struct fragment_program *fprog = ctx->FragmentProgram._Current;
GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
@@ -676,15 +737,9 @@ void intelChooseRenderState(GLcontext *ctx)
*/
if (flags & ANY_FALLBACK_FLAGS)
{
if (flags & POINT_FALLBACK)
intel->draw_point = intel_fallback_point;
if (flags & LINE_FALLBACK)
if (flags & DD_LINE_STIPPLE)
intel->draw_line = intel_fallback_line;
if (flags & TRI_FALLBACK)
intel->draw_tri = intel_fallback_tri;
if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
intel->draw_tri = intel_fallback_tri;
@@ -740,7 +795,7 @@ static const GLenum reduced_prim[GL_POLYGON+1] = {
static void intelRunPipeline( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
if (intel->NewGLState) {
if (intel->NewGLState & _NEW_TEXTURE) {
@@ -760,13 +815,21 @@ static void intelRunPipeline( GLcontext *ctx )
static void intelRenderStart( GLcontext *ctx )
{
INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) );
struct intel_context *intel = intel_context(ctx);
intel->vtbl.render_start( intel_context(ctx) );
intel->vtbl.emit_state( intel );
}
static void intelRenderFinish( GLcontext *ctx )
{
if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT)
struct intel_context *intel = intel_context(ctx);
if (intel->RenderIndex & INTEL_FALLBACK_BIT)
_swrast_flush( ctx );
if (intel->prim.flush)
intel->prim.flush(intel);
}
@@ -777,7 +840,7 @@ static void intelRenderFinish( GLcontext *ctx )
*/
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
if (0)
fprintf(stderr, "%s %s %x\n", __FUNCTION__,
@@ -787,111 +850,185 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
/* Start a new primitive. Arrange to have it flushed later on.
*/
if (hwprim != intel->prim.primitive)
intelStartInlinePrimitive( intel, hwprim );
if (hwprim != intel->prim.primitive) {
if (intel->prim.flush)
intel->prim.flush(intel);
intelStartInlinePrimitive( intel, hwprim, INTEL_BATCH_CLIPRECTS );
}
}
/*
*/
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
{
struct intel_context *intel = intel_context(ctx);
if (0)
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
if (0)
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
/* Let some clipping routines know which primitive they're dealing
* with.
*/
intel->render_primitive = prim;
/* Let some clipping routines know which primitive they're dealing
* with.
*/
intel->render_primitive = prim;
/* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
* triangles. The rasterized primitive will always be reset by
* lower level functions in that case, potentially pingponging the
* state:
*/
if (reduced_prim[prim] == GL_TRIANGLES &&
(ctx->_TriangleCaps & DD_TRI_UNFILLED))
return;
/* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
* triangles. The rasterized primitive will always be reset by
* lower level functions in that case, potentially pingponging the
* state:
*/
if (reduced_prim[prim] == GL_TRIANGLES &&
(ctx->_TriangleCaps & DD_TRI_UNFILLED))
return;
/* Set some primitive-dependent state and Start? a new primitive.
*/
intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
}
/* Set some primitive-dependent state and Start? a new primitive.
*/
intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
}
/**********************************************************************/
/* Transition to/from hardware rasterization. */
/**********************************************************************/
static char *fallbackStrings[] = {
"Texture",
"Draw buffer",
"Read buffer",
"Color mask",
"Render mode",
"Stencil",
"Stipple",
"User disable"
};
static char *fallbackStrings[] = {
"Texture",
"Draw buffer",
"Read buffer",
"Color mask",
"Render mode",
"Stencil",
"Stipple",
"User disable"
};
static char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
static char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode )
{
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint oldfallback = intel->Fallback;
void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode )
{
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint oldfallback = intel->Fallback;
if (mode) {
intel->Fallback |= bit;
if (oldfallback == 0) {
intelFlush(ctx);
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "ENTER FALLBACK %x: %s\n",
bit, getFallbackString( bit ));
_swsetup_Wakeup( ctx );
intel->RenderIndex = ~0;
}
}
else {
intel->Fallback &= ~bit;
if (oldfallback == bit) {
_swrast_flush( ctx );
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
tnl->Driver.Render.Start = intelRenderStart;
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
tnl->Driver.Render.Finish = intelRenderFinish;
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
if (mode) {
intel->Fallback |= bit;
if (oldfallback == 0) {
intelFlush(ctx);
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "ENTER FALLBACK %x: %s\n",
bit, getFallbackString( bit ));
_swsetup_Wakeup( ctx );
intel->RenderIndex = ~0;
}
}
else {
intel->Fallback &= ~bit;
if (oldfallback == bit) {
_swrast_flush( ctx );
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
tnl->Driver.Render.Start = intelRenderStart;
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
tnl->Driver.Render.Finish = intelRenderFinish;
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
_tnl_install_attrs( ctx,
intel->vertex_attrs,
intel->vertex_attr_count,
intel->ViewportMatrix.m, 0 );
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
_tnl_install_attrs( ctx,
intel->vertex_attrs,
intel->vertex_attr_count,
intel->ViewportMatrix.m, 0 );
intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
}
}
}
intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
}
}
}
union fi {
GLfloat f;
GLint i;
};
/**********************************************************************/
/* Used only with the metaops callbacks. */
/**********************************************************************/
void intel_meta_draw_quad(struct intel_context *intel,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLfloat z,
GLuint color,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1)
{
union fi *vb;
if (INTEL_DEBUG & DEBUG_DRI)
fprintf(stderr, "%s: %f,%f-%f,%f 0x%x %f,%f-%f,%f depth: %f\n",
__FUNCTION__,
x0,y0,x1,y1,color,s0,t0,s1,t1, z);
intel->vtbl.emit_state( intel );
/* All 3d primitives should be emitted with INTEL_BATCH_CLIPRECTS,
* otherwise the drawing origin (DR4) might not be set correctly.
*/
intelStartInlinePrimitive( intel, PRIM3D_TRIFAN, INTEL_BATCH_CLIPRECTS );
vb = (union fi *)intelExtendInlinePrimitive( intel, 4 * 6 );
/* initial vertex, left bottom */
vb[0].f = x0;
vb[1].f = y0;
vb[2].f = z;
vb[3].i = color;
vb[4].f = s0;
vb[5].f = t0;
vb += 6;
/* right bottom */
vb[0].f = x1;
vb[1].f = y0;
vb[2].f = z;
vb[3].i = color;
vb[4].f = s1;
vb[5].f = t0;
vb += 6;
/* right top */
vb[0].f = x1;
vb[1].f = y1;
vb[2].f = z;
vb[3].i = color;
vb[4].f = s1;
vb[5].f = t1;
vb += 6;
/* left top */
vb[0].f = x0;
vb[1].f = y1;
vb[2].f = z;
vb[3].i = color;
vb[4].f = s0;
vb[5].f = t1;
if (intel->prim.flush)
intel->prim.flush(intel);
}
/**********************************************************************/

View File

@@ -30,6 +30,8 @@
#include "mtypes.h"
#define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
_DD_NEW_TRI_UNFILLED | \
_DD_NEW_TRI_LIGHT_TWOSIDE | \
@@ -40,7 +42,22 @@
extern void intelInitTriFuncs( GLcontext *ctx );
extern void intelPrintRenderState( const char *msg, GLuint state );
extern void intelChooseRenderState( GLcontext *ctx );
extern void intelStartInlinePrimitive( struct intel_context *intel, GLuint prim, GLuint flags );
extern void intelWrapInlinePrimitive( struct intel_context *intel );
GLuint *intelExtendInlinePrimitive( struct intel_context *intel,
GLuint dwords );
void intel_meta_draw_quad(struct intel_context *intel,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLfloat z,
GLuint color,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1);
#endif

View File

@@ -18,11 +18,21 @@ OUTPUTS = glprocs.h glapitemp.h glapioffsets.h glapitable.h dispatch.h \
../../glx/x11/indirect_size.h \
../../glx/x11/indirect_size.c
#XORG_BASE = /home/idr/devel/graphics/Xorg/xserver/xorg
GLX_DIR = $(XORG_BASE)/GL/glx
SERVER_OUTPUTS = $(GLX_DIR)/indirect_dispatch.c \
$(GLX_DIR)/indirect_dispatch_swap.c \
$(GLX_DIR)/indirect_dispatch.h
COMMON = gl_XML.py license.py gl_API.xml typeexpr.py
COMMON_GLX = $(COMMON) glX_XML.py glX_proto_common.py
all: $(OUTPUTS)
server: $(SERVER_OUTPUTS)
glprocs.h: $(COMMON) gl_procs.py
$(PYTHON2) $(PYTHON_FLAGS) gl_procs.py > glprocs.h
@@ -65,6 +75,21 @@ dispatch.h: $(COMMON) gl_table.py
../../glx/x11/indirect_size.c: $(COMMON_GLX) glX_proto_size.py
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_c --only-set > ../../glx/x11/indirect_size.c
$(GLX_DIR)/indirect_dispatch.c: $(COMMON_GLX) glX_proto_recv.py
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_c > $@
$(GLX_DIR)/indirect_dispatch_swap.c: $(COMMON_GLX) glX_proto_recv.py
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_c -s > $@
$(GLX_DIR)/indirect_dispatch.h: $(COMMON_GLX) glX_proto_recv.py
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_h -s > $@
$(GLX_DIR)/indirect_size_get.h: $(COMMON_GLX) glX_proto_size.py
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_h --only-get -h '_INDIRECT_SIZE_GET_H_' > $@
$(GLX_DIR)/indirect_size_get.c: $(COMMON_GLX) glX_proto_size.py
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_c > $@
clean:
rm -f *~ *.pyo
rm -f $(OUTPUTS)

View File

@@ -2512,10 +2512,13 @@
#define CALL_GetQueryObjectui64vEXT(disp, parameters) (*((disp)->GetQueryObjectui64vEXT)) parameters
#define GET_GetQueryObjectui64vEXT(disp) ((disp)->GetQueryObjectui64vEXT)
#define SET_GetQueryObjectui64vEXT(disp, fn) ((disp)->GetQueryObjectui64vEXT = fn)
#define CALL_BlitFramebufferEXT(disp, parameters) (*((disp)->BlitFramebufferEXT)) parameters
#define GET_BlitFramebufferEXT(disp) ((disp)->BlitFramebufferEXT)
#define SET_BlitFramebufferEXT(disp, fn) ((disp)->BlitFramebufferEXT = fn)
#else
#define driDispatchRemapTable_size 410
#define driDispatchRemapTable_size 411
extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
#define LoadTransposeMatrixfARB_remap_index 0
@@ -2928,6 +2931,7 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
#define StencilMaskSeparate_remap_index 407
#define GetQueryObjecti64vEXT_remap_index 408
#define GetQueryObjectui64vEXT_remap_index 409
#define BlitFramebufferEXT_remap_index 410
#define CALL_LoadTransposeMatrixfARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index], parameters)
#define GET_LoadTransposeMatrixfARB(disp) GET_by_offset(disp, driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index])
@@ -4159,6 +4163,9 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
#define CALL_GetQueryObjectui64vEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLuint64EXT *)), driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index], parameters)
#define GET_GetQueryObjectui64vEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index])
#define SET_GetQueryObjectui64vEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index], fn)
#define CALL_BlitFramebufferEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)), driDispatchRemapTable[BlitFramebufferEXT_remap_index], parameters)
#define GET_BlitFramebufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index])
#define SET_BlitFramebufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index], fn)
#endif /* !defined(IN_DRI_DRIVER) */

View File

@@ -48,7 +48,7 @@ class glx_proto_type(gl_XML.gl_type):
class glx_print_proto(gl_XML.gl_print_base):
def size_call(self, func):
def size_call(self, func, outputs_also = 0):
"""Create C code to calculate 'compsize'.
Creates code to calculate 'compsize'. If the function does
@@ -58,7 +58,7 @@ class glx_print_proto(gl_XML.gl_print_base):
compsize = None
for param in func.parameterIterator():
if not param.is_output:
if outputs_also or not param.is_output:
if param.is_image():
[dim, w, h, d, junk] = param.get_dimensions()

View File

@@ -0,0 +1,561 @@
#!/usr/bin/env python
# (C) Copyright IBM Corporation 2005
# All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# on the rights to use, copy, modify, merge, publish, distribute, sub
# license, and/or sell copies of the Software, and to permit persons to whom
# the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# Authors:
# Ian Romanick <idr@us.ibm.com>
import gl_XML, glX_XML, glX_proto_common, license
import sys, getopt, string
class PrintGlxDispatch_h(gl_XML.gl_print_base):
def __init__(self):
gl_XML.gl_print_base.__init__(self)
self.name = "glX_proto_recv.py (from Mesa)"
self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
self.header_tag = "_INDIRECT_DISPATCH_H_"
return
def printRealHeader(self):
self.printVisibility( "HIDDEN", "hidden" )
print 'struct __GLXclientStateRec;'
print ''
return
def printBody(self, api):
for func in api.functionIterateAll():
if not func.ignore and not func.vectorequiv:
if func.glx_rop != 0:
print 'extern HIDDEN void __glXDisp_%s(GLbyte * pc);' % (func.name)
print 'extern HIDDEN void __glXDispSwap_%s(GLbyte * pc);' % (func.name)
elif func.glx_sop != 0 or func.glx_vendorpriv != 0:
print 'extern HIDDEN int __glXDisp_%s(struct __GLXclientStateRec *, GLbyte *);' % (func.name)
print 'extern HIDDEN int __glXDispSwap_%s(struct __GLXclientStateRec *, GLbyte *);' % (func.name)
return
class PrintGlxDispatchFunctions(glX_proto_common.glx_print_proto):
def __init__(self, do_swap):
gl_XML.gl_print_base.__init__(self)
self.name = "glX_proto_recv.py (from Mesa)"
self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
self.real_types = [ '', '', 'uint16_t', '', 'uint32_t', '', '', '', 'uint64_t' ]
self.do_swap = do_swap
return
def printRealHeader(self):
print '#include <X11/Xmd.h>'
print '#include <GL/gl.h>'
print '#include <GL/glxproto.h>'
# FIXME: Since this block will require changes as other
# FIXME: platforms are added, it should probably be in a
# FIXME: header file that is not generated by a script.
if self.do_swap:
print '#ifdef __linux__'
print '#include <byteswap.h>'
print '#elif defined(__OpenBSD__)'
print '#include <sys/endian.h>'
print '#define bswap_16 __swap16'
print '#define bswap_32 __swap32'
print '#define bswap_64 __swap64'
print '#else'
print '#include <sys/endian.h>'
print '#define bswap_16 bswap16'
print '#define bswap_32 bswap32'
print '#define bswap_64 bswap64'
print '#endif'
print '#include <inttypes.h>'
print '#include "indirect_size.h"'
print '#include "indirect_size_get.h"'
print '#include "indirect_dispatch.h"'
print '#include "glxserver.h"'
print '#include "indirect_util.h"'
print '#include "singlesize.h"'
print '#include "glapitable.h"'
print '#include "glapi.h"'
print '#include "glthread.h"'
print '#include "dispatch.h"'
print ''
print '#define __GLX_PAD(x) (((x) + 3) & ~3)'
print ''
print 'typedef struct {'
print ' __GLX_PIXEL_3D_HDR;'
print '} __GLXpixel3DHeader;'
print ''
print 'extern GLboolean __glXErrorOccured( void );'
print 'extern void __glXClearErrorOccured( void );'
print ''
print 'static const unsigned dummy_answer[2] = {0, 0};'
print ''
return
def printBody(self, api):
if self.do_swap:
self.emit_swap_wrappers(api)
for func in api.functionIterateByOffset():
if not func.ignore and not func.server_handcode and not func.vectorequiv and (func.glx_rop or func.glx_sop or func.glx_vendorpriv):
self.printFunction(func)
return
def printFunction(self, f):
if (f.glx_sop or f.glx_vendorpriv) and (len(f.get_images()) != 0):
return
if not self.do_swap:
base = '__glXDisp'
else:
base = '__glXDispSwap'
if f.glx_rop:
print 'void %s_%s(GLbyte * pc)' % (base, f.name)
else:
print 'int %s_%s(__GLXclientState *cl, GLbyte *pc)' % (base, f.name)
print '{'
if f.glx_rop or f.vectorequiv:
self.printRenderFunction(f)
elif f.glx_sop or f.glx_vendorpriv:
if len(f.get_images()) == 0:
self.printSingleFunction(f)
else:
print "/* Missing GLX protocol for %s. */" % (f.name)
print '}'
print ''
return
def swap_name(self, bytes):
return 'bswap_%u_array' % (8 * bytes)
def emit_swap_wrappers(self, api):
self.type_map = {}
already_done = [ ]
for t in api.typeIterate():
te = t.get_type_expression()
t_size = te.get_element_size()
if t_size > 1 and t.glx_name:
t_name = "GL" + t.name
self.type_map[ t_name ] = t.glx_name
if t.glx_name not in already_done:
real_name = self.real_types[t_size]
print 'static %s' % (t_name)
print 'bswap_%s( const void * src )' % (t.glx_name)
print '{'
print ' union { %s dst; %s ret; } x;' % (real_name, t_name)
print ' x.dst = bswap_%u( *(%s *) src );' % (t_size * 8, real_name)
print ' return x.ret;'
print '}'
print ''
already_done.append( t.glx_name )
for bits in [16, 32, 64]:
print 'static void *'
print 'bswap_%u_array( uint%u_t * src, unsigned count )' % (bits, bits)
print '{'
print ' unsigned i;'
print ''
print ' for ( i = 0 ; i < count ; i++ ) {'
print ' uint%u_t temp = bswap_%u( src[i] );' % (bits, bits)
print ' src[i] = temp;'
print ' }'
print ''
print ' return src;'
print '}'
print ''
def fetch_param(self, param):
t = param.type_string()
o = param.offset
element_size = param.size() / param.get_element_count()
if self.do_swap and (element_size != 1):
if param.is_array():
real_name = self.real_types[ element_size ]
swap_func = self.swap_name( element_size )
return ' (%-8s)%s( (%s *) (pc + %2s), %s )' % (t, swap_func, real_name, o, param.count)
else:
t_name = param.get_base_type_string()
return ' (%-8s)bswap_%-7s( pc + %2s )' % (t, self.type_map[ t_name ], o)
else:
if param.is_array():
return ' (%-8s)(pc + %2u)' % (t, o)
else:
return '*(%-8s *)(pc + %2u)' % (t, o)
return None
def emit_function_call(self, f, retval_assign, indent):
list = []
for param in f.parameterIterator():
if param.is_counter or param.is_image() or param.is_output or len(param.count_parameter_list):
location = param.name
else:
location = self.fetch_param(param)
list.append( '%s %s' % (indent, location) )
if len( list ):
print '%s %sCALL_%s( GET_DISPATCH(), (' % (indent, retval_assign, f.name)
print string.join( list, ",\n" )
print '%s ) );' % (indent)
else:
print '%s %sCALL_%s( GET_DISPATCH(), () );' % (indent, retval_assign, f.name)
return
def common_func_print_just_start(self, f, indent):
align64 = 0
need_blank = 0
f.calculate_offsets()
for param in f.parameterIterateGlxSend():
# If any parameter has a 64-bit base type, then we
# have to do alignment magic for the while thing.
if param.is_64_bit():
align64 = 1
# FIXME img_null_flag is over-loaded. In addition to
# FIXME being used for images, it is used to signify
# FIXME NULL data pointers for vertex buffer object
# FIXME related functions. Re-name it to null_data
# FIXME or something similar.
if param.img_null_flag:
print '%s const CARD32 ptr_is_null = *(CARD32 *)(pc + %s);' % (indent, param.offset - 4)
cond = '(ptr_is_null != 0) ? NULL : '
else:
cond = ""
type_string = param.type_string()
if param.is_image():
offset = f.offset_of( param.name )
print '%s %s const %s = (%s) %s(pc + %s);' % (indent, type_string, param.name, type_string, cond, offset)
if param.depth:
print '%s __GLXpixel3DHeader * const hdr = (__GLXpixel3DHeader *)(pc);' % (indent)
else:
print '%s __GLXpixelHeader * const hdr = (__GLXpixelHeader *)(pc);' % (indent)
need_blank = 1
elif param.is_counter or param.name in f.count_parameter_list:
location = self.fetch_param(param)
print '%s const %s %s = %s;' % (indent, type_string, param.name, location)
need_blank = 1
elif len(param.count_parameter_list):
if param.size() == 1 and not self.do_swap:
location = self.fetch_param(param)
print '%s %s %s = %s%s;' % (indent, type_string, param.name, cond, location)
else:
print '%s %s %s;' % (indent, type_string, param.name)
need_blank = 1
if need_blank:
print ''
if align64:
print '#ifdef __GLX_ALIGN64'
if f.has_variable_size_request():
self.emit_packet_size_calculation(f, 4)
s = "cmdlen"
else:
s = str((f.command_fixed_length() + 3) & ~3)
print ' if ((unsigned long)(pc) & 7) {'
print ' (void) memmove(pc-4, pc, %s);' % (s)
print ' pc -= 4;'
print ' }'
print '#endif'
print ''
need_blank = 0
if self.do_swap:
for param in f.parameterIterateGlxSend():
if param.count_parameter_list:
o = param.offset
count = param.get_element_count()
type_size = param.size() / count
if param.counter:
count_name = param.counter
else:
count_name = str(count)
# This is basically an ugly special-
# case for glCallLists.
if type_size == 1:
x = []
x.append( [1, ['BYTE', 'UNSIGNED_BYTE', '2_BYTES', '3_BYTES', '4_BYTES']] )
x.append( [2, ['SHORT', 'UNSIGNED_SHORT']] )
x.append( [4, ['INT', 'UNSIGNED_INT', 'FLOAT']] )
print ' switch(%s) {' % (param.count_parameter_list[0])
for sub in x:
for t_name in sub[1]:
print ' case GL_%s:' % (t_name)
if sub[0] == 1:
print ' %s = (%s) (pc + %s); break;' % (param.name, param.type_string(), o)
else:
swap_func = self.swap_name(sub[0])
print ' %s = (%s) %s( (%s *) (pc + %s), %s ); break;' % (param.name, param.type_string(), swap_func, self.real_types[sub[0]], o, count_name)
print ' }'
else:
swap_func = self.swap_name(type_size)
compsize = self.size_call(f, 1)
print ' %s = (%s) %s( (%s *) (pc + %s), %s );' % (param.name, param.type_string(), swap_func, self.real_types[type_size], o, compsize)
need_blank = 1
else:
for param in f.parameterIterateGlxSend():
if param.count_parameter_list:
print '%s %s = (%s) (pc + %s);' % (indent, param.name, param.type_string(), param.offset)
need_blank = 1
if need_blank:
print ''
return
def printSingleFunction(self, f):
if f.glx_sop:
print ' xGLXSingleReq * const req = (xGLXSingleReq *) pc;'
else:
print ' xGLXVendorPrivateReq * const req = (xGLXVendorPrivateReq *) pc;'
print ' int error;'
if self.do_swap:
print ' __GLXcontext * const cx = __glXForceCurrent(cl, bswap_CARD32( &req->contextTag ), &error);'
else:
print ' __GLXcontext * const cx = __glXForceCurrent(cl, req->contextTag, &error);'
print ''
if f.glx_sop:
print ' pc += __GLX_SINGLE_HDR_SIZE;'
else:
print ' pc += __GLX_VENDPRIV_HDR_SIZE;'
print ' if ( cx != NULL ) {'
self.common_func_print_just_start(f, " ")
if f.return_type != 'void':
print ' %s retval;' % (f.return_type)
retval_string = "retval"
retval_assign = "retval = "
else:
retval_string = "0"
retval_assign = ""
type_size = 0
answer_string = "dummy_answer"
answer_count = "0"
is_array_string = "GL_FALSE"
for param in f.parameterIterateOutputs():
answer_type = param.get_base_type_string()
if answer_type == "GLvoid":
answer_type = "GLubyte"
c = param.get_element_count()
type_size = (param.size() / c)
if type_size == 1:
size_scale = ""
else:
size_scale = " * %u" % (type_size)
if param.count_parameter_list:
print ' const GLuint compsize = %s;' % (self.size_call(f, 1))
print ' %s answerBuffer[200];' % (answer_type)
print ' %s %s = __glXGetAnswerBuffer(cl, compsize%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, size_scale, type_size )
answer_string = param.name
answer_count = "compsize"
print ''
print ' if (%s == NULL) return BadAlloc;' % (param.name)
print ' __glXClearErrorOccured();'
print ''
elif param.counter:
print ' %s answerBuffer[200];' % (answer_type)
print ' %s %s = __glXGetAnswerBuffer(cl, %s%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, param.counter, size_scale, type_size)
answer_string = param.name
answer_count = param.counter
elif c >= 1:
print ' %s %s[%u];' % (answer_type, param.name, c)
answer_string = param.name
answer_count = "%u" % (c)
if f.reply_always_array:
is_array_string = "GL_TRUE"
self.emit_function_call(f, retval_assign, " ")
if f.needs_reply():
if self.do_swap:
for param in f.parameterIterateOutputs():
c = param.get_element_count()
type_size = (param.size() / c)
if type_size > 1:
swap_name = self.swap_name( type_size )
print ' (void) %s( (uint%u_t *) %s, %s );' % (swap_name, 8 * type_size, param.name, answer_count)
reply_func = '__glXSendReplySwap'
else:
reply_func = '__glXSendReply'
print ' %s(cl->client, %s, %s, %u, %s, %s);' % (reply_func, answer_string, answer_count, type_size, is_array_string, retval_string)
#elif f.note_unflushed:
# print ' cx->hasUnflushedCommands = GL_TRUE;'
print ' error = Success;'
print ' }'
print ''
print ' return error;'
return
def printRenderFunction(self, f):
# There are 4 distinct phases in a rendering dispatch function.
# In the first phase we compute the sizes and offsets of each
# element in the command. In the second phase we (optionally)
# re-align 64-bit data elements. In the third phase we
# (optionally) byte-swap array data. Finally, in the fourth
# phase we actually dispatch the function.
self.common_func_print_just_start(f, "")
images = f.get_images()
if len(images):
if self.do_swap:
pre = "bswap_CARD32( & "
post = " )"
else:
pre = ""
post = ""
img = images[0]
# swapBytes and lsbFirst are single byte fields, so
# the must NEVER be byte-swapped.
if not (img.img_type == "GL_BITMAP" and img.img_format == "GL_COLOR_INDEX"):
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, hdr->swapBytes) );'
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, hdr->lsbFirst) );'
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, (GLint) %shdr->rowLength%s) );' % (pre, post)
if img.depth:
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_IMAGE_HEIGHT, (GLint) %shdr->imageHeight%s) );' % (pre, post)
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, (GLint) %shdr->skipRows%s) );' % (pre, post)
if img.depth:
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_IMAGES, (GLint) %shdr->skipImages%s) );' % (pre, post)
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, (GLint) %shdr->skipPixels%s) );' % (pre, post)
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, (GLint) %shdr->alignment%s) );' % (pre, post)
print ''
self.emit_function_call(f, "", "")
return
if __name__ == '__main__':
file_name = "gl_API.xml"
try:
(args, trail) = getopt.getopt(sys.argv[1:], "f:m:s")
except Exception,e:
show_usage()
mode = "dispatch_c"
do_swap = 0
for (arg,val) in args:
if arg == "-f":
file_name = val
elif arg == "-m":
mode = val
elif arg == "-s":
do_swap = 1
if mode == "dispatch_c":
printer = PrintGlxDispatchFunctions(do_swap)
elif mode == "dispatch_h":
printer = PrintGlxDispatch_h()
else:
show_usage()
api = gl_XML.parse_GL_API( file_name, glX_proto_common.glx_proto_item_factory() )
printer.Print( api )

View File

@@ -879,7 +879,7 @@ __GLapi * __glXNewIndirectAPI( void )
if first:
print ''
if show_num:
print ' /* % 3u. %s */' % (cat_num, cat_name)
print ' /* %3u. %s */' % (cat_num, cat_name)
else:
print ' /* %s */' % (cat_name)
print ''

View File

@@ -10447,8 +10447,8 @@
<function name="GenProgramsNV" offset="582">
<param name="n" type="GLsizei" counter="true"/>
<param name="programs" type="GLuint *" output="true" count="n"/>
<glx vendorpriv="1295"/>
</function>
<glx vendorpriv="1295" always_array="true"/>
</function>
<!-- This isn't 100% correct. Currently, the only valid value of pname
is GL_PROGRAM_PARAMETER_NV, and the count for that pname is always
@@ -11498,4 +11498,23 @@
</function>
</category>
<category name="GL_EXT_framebuffer_blit" number="316">
<enum name="GL_READ_FRAMEBUFFER_EXT" value="0x8CA8"/>
<enum name="GL_DRAW_FRAMEBUFFER_EXT" value="0x8CA9"/>
<enum name="GL_DRAW_FRAMEBUFFER_BINDING_EXT" value="0x8CA6"/>
<enum name="GL_READ_FRAMEBUFFER_BINDING_EXT" value="0x8CAA"/>
<function name="BlitFramebufferEXT" offset="818">
<param name="srcX0" type="GLint"/>
<param name="srcY0" type="GLint"/>
<param name="srcX1" type="GLint"/>
<param name="srcY1" type="GLint"/>
<param name="dstX0" type="GLint"/>
<param name="dstY0" type="GLint"/>
<param name="dstX1" type="GLint"/>
<param name="dstY1" type="GLint"/>
<param name="mask" type="GLbitfield"/>
<param name="filter" type="GLenum"/>
</function>
</category>
</OpenGLAPI>

View File

@@ -161,7 +161,7 @@ int _mesa_lookup_enum_by_name( const char *symbol )
print 'static const enum_elt all_enums[%u] =' % (len(name_table))
print '{'
for [name, enum] in name_table:
print ' { % 5u, 0x%08X }, /* %s */' % (string_offsets[name], enum, name)
print ' { %5u, 0x%08X }, /* %s */' % (string_offsets[name], enum, name)
print '};'
print ''
@@ -174,7 +174,7 @@ int _mesa_lookup_enum_by_name( const char *symbol )
else:
i = name_table.index( [name, enum] )
print ' % 4u, /* %s */' % (i, name)
print ' %4u, /* %s */' % (i, name)
print '};'

View File

@@ -113,7 +113,7 @@ class PrintGlProcs(gl_XML.gl_print_base):
print 'static const glprocs_table_t static_functions[] = {'
for (offset, disp_name, real_name) in table:
print ' NAME_FUNC_OFFSET( % 5u, gl%s, _gloffset_%s ),' % (offset, disp_name, real_name)
print ' NAME_FUNC_OFFSET( %5u, gl%s, _gloffset_%s ),' % (offset, disp_name, real_name)
print ' NAME_FUNC_OFFSET( -1, NULL, 0 )'
print '};'

View File

@@ -1,8 +1,8 @@
/*
* Mesa 3-D graphics library
* Version: 6.3
* Version: 6.5
*
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -54,7 +54,6 @@
#include "glapi.h"
#include "glapioffsets.h"
#include "glapitable.h"
#include "glthread.h"
/***** BEGIN NO-OP DISPATCH *****/
@@ -287,14 +286,14 @@ _glapi_get_context(void)
/**
* Set the global or per-thread dispatch table pointer.
* If the dispatch parameter is NULL we'll plug in the no-op dispatch
* table (__glapi_noop_table).
*/
PUBLIC void
_glapi_set_dispatch(struct _glapi_table *dispatch)
{
#if defined(PTHREADS) || defined(GLX_USE_TLS)
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
pthread_once( & once_control, init_glapi_relocs );
#endif
@@ -327,7 +326,6 @@ PUBLIC struct _glapi_table *
_glapi_get_dispatch(void)
{
struct _glapi_table * api;
#if defined(GLX_USE_TLS)
api = _glapi_tls_Dispatch;
#elif defined(THREADS)
@@ -337,13 +335,17 @@ _glapi_get_dispatch(void)
#else
api = _glapi_Dispatch;
#endif
assert( api != NULL );
return api;
}
#if !defined( USE_X86_ASM ) && !defined( XFree86Server )
/***
*** The rest of this file is pretty much concerned with GetProcAddress
*** functionality.
***/
#if !defined( USE_X86_ASM ) && !defined( XFree86Server ) && !defined ( XGLServer )
#define NEED_FUNCTION_POINTER
#endif
@@ -359,13 +361,10 @@ static const glprocs_table_t *
find_entry( const char * n )
{
GLuint i;
for (i = 0; static_functions[i].Name_offset >= 0; i++) {
const char * test_name;
test_name = gl_string_table + static_functions[i].Name_offset;
if (strcmp(test_name, n) == 0) {
return & static_functions[i];
const char *testName = gl_string_table + static_functions[i].Name_offset;
if (strcmp(testName, n) == 0) {
return &static_functions[i];
}
}
return NULL;
@@ -380,15 +379,14 @@ static GLint
get_static_proc_offset(const char *funcName)
{
const glprocs_table_t * const f = find_entry( funcName );
if ( f != NULL ) {
if (f) {
return f->Offset;
}
return -1;
}
#if !defined( XFree86Server )
#if !defined(XFree86Server) && !defined(XGLServer)
#ifdef USE_X86_ASM
#if defined( GLX_USE_TLS )
@@ -404,42 +402,33 @@ extern const GLubyte gl_dispatch_functions_start[];
# define X86_DISPATCH_FUNCTION_SIZE 16
# endif
#endif /* USE_X86_ASM */
/**
* Return dispatch function address the named static (built-in) function.
* Return dispatch function address for the named static (built-in) function.
* Return NULL if function not found.
*/
static const _glapi_proc
get_static_proc_address(const char *funcName)
{
const glprocs_table_t * const f = find_entry( funcName );
if ( f != NULL ) {
if (f) {
#ifdef USE_X86_ASM
return (_glapi_proc) (gl_dispatch_functions_start
+ (X86_DISPATCH_FUNCTION_SIZE * f->Offset));
#else
return f->Address;
#endif
}
else {
return NULL;
}
}
#else
#endif /* !defined(XFree86Server) && !defined(XGLServer) */
/**
* Return pointer to the named static (built-in) function.
* \return NULL if function not found.
*/
static const _glapi_proc
get_static_proc_address(const char *funcName)
{
const glprocs_table_t * const f = find_entry( funcName );
return ( f != NULL ) ? f->Address : NULL;
}
#endif /* USE_X86_ASM */
#endif /* !defined( XFree86Server ) */
/**
* Return the name of the function at the given offset in the dispatch
@@ -449,7 +438,6 @@ static const char *
get_static_proc_name( GLuint offset )
{
GLuint i;
for (i = 0; static_functions[i].Name_offset >= 0; i++) {
if (static_functions[i].Offset == offset) {
return gl_string_table + static_functions[i].Name_offset;
@@ -579,7 +567,7 @@ generate_entrypoint(GLuint functionOffset)
0x81c0c000, /* jmpl %g3, %g0 */
0x01000000 /* nop */
};
#endif
#endif /* __arch64__ */
unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
if (code) {
@@ -601,7 +589,7 @@ generate_entrypoint(GLuint functionOffset)
__glapi_sparc_icache_flush(&code[0]);
code[2] |= (functionOffset * 4);
__glapi_sparc_icache_flush(&code[2]);
#endif
#endif /* __arch64__ */
}
return (_glapi_proc) code;
#else
@@ -621,7 +609,6 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
#if defined(USE_X86_ASM)
GLubyte * const code = (GLubyte *) entrypoint;
#if X86_DISPATCH_FUNCTION_SIZE == 32
*((unsigned int *)(code + 11)) = 4 * offset;
*((unsigned int *)(code + 22)) = 4 * offset;
@@ -763,14 +750,8 @@ _glapi_add_dispatch( const char * const * function_names,
/* Do some trivial validation on the name of the function.
*/
#ifdef MANGLE
if (!function_names[i] || function_names[i][0] != 'm' || function_names[i][1] != 'g' || function_names[i][2] != 'l')
return GL_FALSE;
#else
if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l')
return GL_FALSE;
#endif
/* Determine if the named function already exists. If the function does
* exist, it must have the same parameter signature as the function
@@ -817,13 +798,11 @@ _glapi_add_dispatch( const char * const * function_names,
}
}
if (offset == ~0) {
offset = next_dynamic_offset;
next_dynamic_offset++;
}
for ( i = 0 ; function_names[i] != NULL ; i++ ) {
if (! is_static[i] ) {
if (entry[i] == NULL) {
@@ -835,7 +814,6 @@ _glapi_add_dispatch( const char * const * function_names,
}
}
entry[i]->parameter_signature = str_dup(real_sig);
fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset);
entry[i]->dispatch_offset = offset;
@@ -859,7 +837,6 @@ _glapi_get_proc_offset(const char *funcName)
return ExtEntryTable[i].dispatch_offset;
}
}
/* search static functions */
return get_static_proc_offset(funcName);
}
@@ -892,7 +869,7 @@ _glapi_get_proc_address(const char *funcName)
}
}
#if !defined( XFree86Server )
#if !defined( XFree86Server ) && !defined( XGLServer )
/* search static functions */
{
const _glapi_proc func = get_static_proc_address(funcName);

View File

@@ -1,8 +1,8 @@
/*
* Mesa 3-D graphics library
* Version: 6.3
* Version: 6.5
*
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -47,10 +47,26 @@
#include "GL/gl.h"
#include "glapitable.h"
#include "glthread.h"
typedef void (*_glapi_warning_func)(void *ctx, const char *str, ...);
#if defined(USE_MGL_NAMESPACE)
#define _glapi_set_dispatch _mglapi_set_dispatch
#define _glapi_get_dispatch _mglapi_get_dispatch
#define _glapi_set_context _mglapi_set_context
#define _glapi_get_context _mglapi_get_context
#define _glapi_Context _mglapi_Context
#define _glapi_Dispatch _mglapi_Dispatch
#endif
/**
** Define the GET_CURRENT_CONTEXT() macro.
** \param C local variable which will hold the current context.
**/
#if defined (GLX_USE_TLS)
const extern void *_glapi_Context;
@@ -66,19 +82,6 @@ extern __thread void * _glapi_tls_Context
extern void *_glapi_Context;
extern struct _glapi_table *_glapi_Dispatch;
/**
* Macro for declaration and fetching the current context.
*
* \param C local variable which will hold the current context.
*
* It should be used in the variable declaration area of a function:
* \code
* ...
* {
* GET_CURRENT_CONTEXT(ctx);
* ...
* \endcode
*/
# ifdef THREADS
# define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context())
# else
@@ -87,6 +90,11 @@ extern struct _glapi_table *_glapi_Dispatch;
#endif /* defined (GLX_USE_TLS) */
/**
** GL API public functions
**/
extern void
_glapi_noop_enable_warnings(GLboolean enable);

View File

@@ -850,7 +850,8 @@
#define _gloffset_StencilMaskSeparate 815
#define _gloffset_GetQueryObjecti64vEXT 816
#define _gloffset_GetQueryObjectui64vEXT 817
#define _gloffset_FIRST_DYNAMIC 818
#define _gloffset_BlitFramebufferEXT 818
#define _gloffset_FIRST_DYNAMIC 819
#else
@@ -1264,6 +1265,7 @@
#define _gloffset_StencilMaskSeparate driDispatchRemapTable[StencilMaskSeparate_remap_index]
#define _gloffset_GetQueryObjecti64vEXT driDispatchRemapTable[GetQueryObjecti64vEXT_remap_index]
#define _gloffset_GetQueryObjectui64vEXT driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index]
#define _gloffset_BlitFramebufferEXT driDispatchRemapTable[BlitFramebufferEXT_remap_index]
#endif /* !defined(IN_DRI_DRIVER) */

View File

@@ -855,6 +855,7 @@ struct _glapi_table
void (GLAPIENTRYP StencilMaskSeparate)(GLenum face, GLuint mask); /* 815 */
void (GLAPIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT * params); /* 816 */
void (GLAPIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT * params); /* 817 */
void (GLAPIENTRYP BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); /* 818 */
};
#endif /* !defined( _GLAPI_TABLE_H_ ) */

View File

@@ -5050,6 +5050,11 @@ KEYWORD1 void KEYWORD2 NAME(GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLu
DISPATCH(GetQueryObjectui64vEXT, (id, pname, params), (F, "glGetQueryObjectui64vEXT(%d, 0x%x, %p);\n", id, pname, (const void *) params));
}
KEYWORD1 void KEYWORD2 NAME(BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
DISPATCH(BlitFramebufferEXT, (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), (F, "glBlitFramebufferEXT(%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x);\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter));
}
#endif /* defined( NAME ) */
@@ -5882,6 +5887,7 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
TABLE_ENTRY(StencilMaskSeparate),
TABLE_ENTRY(GetQueryObjecti64vEXT),
TABLE_ENTRY(GetQueryObjectui64vEXT),
TABLE_ENTRY(BlitFramebufferEXT),
/* A whole bunch of no-op functions. These might be called
* when someone tries to call a dynamically-registered
* extension function without a current rendering context.

View File

@@ -864,6 +864,7 @@ static const char gl_string_table[] =
"glStencilMaskSeparate\0"
"glGetQueryObjecti64vEXT\0"
"glGetQueryObjectui64vEXT\0"
"glBlitFramebufferEXT\0"
"glArrayElementEXT\0"
"glBindTextureEXT\0"
"glDrawArraysEXT\0"
@@ -1863,184 +1864,185 @@ static const glprocs_table_t static_functions[] = {
NAME_FUNC_OFFSET( 14649, glStencilMaskSeparate, _gloffset_StencilMaskSeparate ),
NAME_FUNC_OFFSET( 14671, glGetQueryObjecti64vEXT, _gloffset_GetQueryObjecti64vEXT ),
NAME_FUNC_OFFSET( 14695, glGetQueryObjectui64vEXT, _gloffset_GetQueryObjectui64vEXT ),
NAME_FUNC_OFFSET( 14720, glArrayElementEXT, _gloffset_ArrayElement ),
NAME_FUNC_OFFSET( 14738, glBindTextureEXT, _gloffset_BindTexture ),
NAME_FUNC_OFFSET( 14755, glDrawArraysEXT, _gloffset_DrawArrays ),
NAME_FUNC_OFFSET( 14771, glCopyTexImage1DEXT, _gloffset_CopyTexImage1D ),
NAME_FUNC_OFFSET( 14791, glCopyTexImage2DEXT, _gloffset_CopyTexImage2D ),
NAME_FUNC_OFFSET( 14811, glCopyTexSubImage1DEXT, _gloffset_CopyTexSubImage1D ),
NAME_FUNC_OFFSET( 14834, glCopyTexSubImage2DEXT, _gloffset_CopyTexSubImage2D ),
NAME_FUNC_OFFSET( 14857, glDeleteTexturesEXT, _gloffset_DeleteTextures ),
NAME_FUNC_OFFSET( 14877, glGetPointervEXT, _gloffset_GetPointerv ),
NAME_FUNC_OFFSET( 14894, glPrioritizeTexturesEXT, _gloffset_PrioritizeTextures ),
NAME_FUNC_OFFSET( 14918, glTexSubImage1DEXT, _gloffset_TexSubImage1D ),
NAME_FUNC_OFFSET( 14937, glTexSubImage2DEXT, _gloffset_TexSubImage2D ),
NAME_FUNC_OFFSET( 14956, glBlendColorEXT, _gloffset_BlendColor ),
NAME_FUNC_OFFSET( 14972, glBlendEquationEXT, _gloffset_BlendEquation ),
NAME_FUNC_OFFSET( 14991, glDrawRangeElementsEXT, _gloffset_DrawRangeElements ),
NAME_FUNC_OFFSET( 15014, glColorTableSGI, _gloffset_ColorTable ),
NAME_FUNC_OFFSET( 15030, glColorTableEXT, _gloffset_ColorTable ),
NAME_FUNC_OFFSET( 15046, glColorTableParameterfvSGI, _gloffset_ColorTableParameterfv ),
NAME_FUNC_OFFSET( 15073, glColorTableParameterivSGI, _gloffset_ColorTableParameteriv ),
NAME_FUNC_OFFSET( 15100, glCopyColorTableSGI, _gloffset_CopyColorTable ),
NAME_FUNC_OFFSET( 15120, glColorSubTableEXT, _gloffset_ColorSubTable ),
NAME_FUNC_OFFSET( 15139, glCopyColorSubTableEXT, _gloffset_CopyColorSubTable ),
NAME_FUNC_OFFSET( 15162, glConvolutionFilter1DEXT, _gloffset_ConvolutionFilter1D ),
NAME_FUNC_OFFSET( 15187, glConvolutionFilter2DEXT, _gloffset_ConvolutionFilter2D ),
NAME_FUNC_OFFSET( 15212, glConvolutionParameterfEXT, _gloffset_ConvolutionParameterf ),
NAME_FUNC_OFFSET( 15239, glConvolutionParameterfvEXT, _gloffset_ConvolutionParameterfv ),
NAME_FUNC_OFFSET( 15267, glConvolutionParameteriEXT, _gloffset_ConvolutionParameteri ),
NAME_FUNC_OFFSET( 15294, glConvolutionParameterivEXT, _gloffset_ConvolutionParameteriv ),
NAME_FUNC_OFFSET( 15322, glCopyConvolutionFilter1DEXT, _gloffset_CopyConvolutionFilter1D ),
NAME_FUNC_OFFSET( 15351, glCopyConvolutionFilter2DEXT, _gloffset_CopyConvolutionFilter2D ),
NAME_FUNC_OFFSET( 15380, glSeparableFilter2DEXT, _gloffset_SeparableFilter2D ),
NAME_FUNC_OFFSET( 15403, glHistogramEXT, _gloffset_Histogram ),
NAME_FUNC_OFFSET( 15418, glMinmaxEXT, _gloffset_Minmax ),
NAME_FUNC_OFFSET( 15430, glResetHistogramEXT, _gloffset_ResetHistogram ),
NAME_FUNC_OFFSET( 15450, glResetMinmaxEXT, _gloffset_ResetMinmax ),
NAME_FUNC_OFFSET( 15467, glTexImage3DEXT, _gloffset_TexImage3D ),
NAME_FUNC_OFFSET( 15483, glTexSubImage3DEXT, _gloffset_TexSubImage3D ),
NAME_FUNC_OFFSET( 15502, glCopyTexSubImage3DEXT, _gloffset_CopyTexSubImage3D ),
NAME_FUNC_OFFSET( 15525, glActiveTexture, _gloffset_ActiveTextureARB ),
NAME_FUNC_OFFSET( 15541, glClientActiveTexture, _gloffset_ClientActiveTextureARB ),
NAME_FUNC_OFFSET( 15563, glMultiTexCoord1d, _gloffset_MultiTexCoord1dARB ),
NAME_FUNC_OFFSET( 15581, glMultiTexCoord1dv, _gloffset_MultiTexCoord1dvARB ),
NAME_FUNC_OFFSET( 15600, glMultiTexCoord1f, _gloffset_MultiTexCoord1fARB ),
NAME_FUNC_OFFSET( 15618, glMultiTexCoord1fv, _gloffset_MultiTexCoord1fvARB ),
NAME_FUNC_OFFSET( 15637, glMultiTexCoord1i, _gloffset_MultiTexCoord1iARB ),
NAME_FUNC_OFFSET( 15655, glMultiTexCoord1iv, _gloffset_MultiTexCoord1ivARB ),
NAME_FUNC_OFFSET( 15674, glMultiTexCoord1s, _gloffset_MultiTexCoord1sARB ),
NAME_FUNC_OFFSET( 15692, glMultiTexCoord1sv, _gloffset_MultiTexCoord1svARB ),
NAME_FUNC_OFFSET( 15711, glMultiTexCoord2d, _gloffset_MultiTexCoord2dARB ),
NAME_FUNC_OFFSET( 15729, glMultiTexCoord2dv, _gloffset_MultiTexCoord2dvARB ),
NAME_FUNC_OFFSET( 15748, glMultiTexCoord2f, _gloffset_MultiTexCoord2fARB ),
NAME_FUNC_OFFSET( 15766, glMultiTexCoord2fv, _gloffset_MultiTexCoord2fvARB ),
NAME_FUNC_OFFSET( 15785, glMultiTexCoord2i, _gloffset_MultiTexCoord2iARB ),
NAME_FUNC_OFFSET( 15803, glMultiTexCoord2iv, _gloffset_MultiTexCoord2ivARB ),
NAME_FUNC_OFFSET( 15822, glMultiTexCoord2s, _gloffset_MultiTexCoord2sARB ),
NAME_FUNC_OFFSET( 15840, glMultiTexCoord2sv, _gloffset_MultiTexCoord2svARB ),
NAME_FUNC_OFFSET( 15859, glMultiTexCoord3d, _gloffset_MultiTexCoord3dARB ),
NAME_FUNC_OFFSET( 15877, glMultiTexCoord3dv, _gloffset_MultiTexCoord3dvARB ),
NAME_FUNC_OFFSET( 15896, glMultiTexCoord3f, _gloffset_MultiTexCoord3fARB ),
NAME_FUNC_OFFSET( 15914, glMultiTexCoord3fv, _gloffset_MultiTexCoord3fvARB ),
NAME_FUNC_OFFSET( 15933, glMultiTexCoord3i, _gloffset_MultiTexCoord3iARB ),
NAME_FUNC_OFFSET( 15951, glMultiTexCoord3iv, _gloffset_MultiTexCoord3ivARB ),
NAME_FUNC_OFFSET( 15970, glMultiTexCoord3s, _gloffset_MultiTexCoord3sARB ),
NAME_FUNC_OFFSET( 15988, glMultiTexCoord3sv, _gloffset_MultiTexCoord3svARB ),
NAME_FUNC_OFFSET( 16007, glMultiTexCoord4d, _gloffset_MultiTexCoord4dARB ),
NAME_FUNC_OFFSET( 16025, glMultiTexCoord4dv, _gloffset_MultiTexCoord4dvARB ),
NAME_FUNC_OFFSET( 16044, glMultiTexCoord4f, _gloffset_MultiTexCoord4fARB ),
NAME_FUNC_OFFSET( 16062, glMultiTexCoord4fv, _gloffset_MultiTexCoord4fvARB ),
NAME_FUNC_OFFSET( 16081, glMultiTexCoord4i, _gloffset_MultiTexCoord4iARB ),
NAME_FUNC_OFFSET( 16099, glMultiTexCoord4iv, _gloffset_MultiTexCoord4ivARB ),
NAME_FUNC_OFFSET( 16118, glMultiTexCoord4s, _gloffset_MultiTexCoord4sARB ),
NAME_FUNC_OFFSET( 16136, glMultiTexCoord4sv, _gloffset_MultiTexCoord4svARB ),
NAME_FUNC_OFFSET( 16155, glLoadTransposeMatrixf, _gloffset_LoadTransposeMatrixfARB ),
NAME_FUNC_OFFSET( 16178, glLoadTransposeMatrixd, _gloffset_LoadTransposeMatrixdARB ),
NAME_FUNC_OFFSET( 16201, glMultTransposeMatrixf, _gloffset_MultTransposeMatrixfARB ),
NAME_FUNC_OFFSET( 16224, glMultTransposeMatrixd, _gloffset_MultTransposeMatrixdARB ),
NAME_FUNC_OFFSET( 16247, glSampleCoverage, _gloffset_SampleCoverageARB ),
NAME_FUNC_OFFSET( 16264, glDrawBuffersATI, _gloffset_DrawBuffersARB ),
NAME_FUNC_OFFSET( 16281, glSampleMaskEXT, _gloffset_SampleMaskSGIS ),
NAME_FUNC_OFFSET( 16297, glSamplePatternEXT, _gloffset_SamplePatternSGIS ),
NAME_FUNC_OFFSET( 16316, glPointParameterf, _gloffset_PointParameterfEXT ),
NAME_FUNC_OFFSET( 16334, glPointParameterfARB, _gloffset_PointParameterfEXT ),
NAME_FUNC_OFFSET( 16355, glPointParameterfSGIS, _gloffset_PointParameterfEXT ),
NAME_FUNC_OFFSET( 16377, glPointParameterfv, _gloffset_PointParameterfvEXT ),
NAME_FUNC_OFFSET( 16396, glPointParameterfvARB, _gloffset_PointParameterfvEXT ),
NAME_FUNC_OFFSET( 16418, glPointParameterfvSGIS, _gloffset_PointParameterfvEXT ),
NAME_FUNC_OFFSET( 16441, glWindowPos2d, _gloffset_WindowPos2dMESA ),
NAME_FUNC_OFFSET( 16455, glWindowPos2dARB, _gloffset_WindowPos2dMESA ),
NAME_FUNC_OFFSET( 16472, glWindowPos2dv, _gloffset_WindowPos2dvMESA ),
NAME_FUNC_OFFSET( 16487, glWindowPos2dvARB, _gloffset_WindowPos2dvMESA ),
NAME_FUNC_OFFSET( 16505, glWindowPos2f, _gloffset_WindowPos2fMESA ),
NAME_FUNC_OFFSET( 16519, glWindowPos2fARB, _gloffset_WindowPos2fMESA ),
NAME_FUNC_OFFSET( 16536, glWindowPos2fv, _gloffset_WindowPos2fvMESA ),
NAME_FUNC_OFFSET( 16551, glWindowPos2fvARB, _gloffset_WindowPos2fvMESA ),
NAME_FUNC_OFFSET( 16569, glWindowPos2i, _gloffset_WindowPos2iMESA ),
NAME_FUNC_OFFSET( 16583, glWindowPos2iARB, _gloffset_WindowPos2iMESA ),
NAME_FUNC_OFFSET( 16600, glWindowPos2iv, _gloffset_WindowPos2ivMESA ),
NAME_FUNC_OFFSET( 16615, glWindowPos2ivARB, _gloffset_WindowPos2ivMESA ),
NAME_FUNC_OFFSET( 16633, glWindowPos2s, _gloffset_WindowPos2sMESA ),
NAME_FUNC_OFFSET( 16647, glWindowPos2sARB, _gloffset_WindowPos2sMESA ),
NAME_FUNC_OFFSET( 16664, glWindowPos2sv, _gloffset_WindowPos2svMESA ),
NAME_FUNC_OFFSET( 16679, glWindowPos2svARB, _gloffset_WindowPos2svMESA ),
NAME_FUNC_OFFSET( 16697, glWindowPos3d, _gloffset_WindowPos3dMESA ),
NAME_FUNC_OFFSET( 16711, glWindowPos3dARB, _gloffset_WindowPos3dMESA ),
NAME_FUNC_OFFSET( 16728, glWindowPos3dv, _gloffset_WindowPos3dvMESA ),
NAME_FUNC_OFFSET( 16743, glWindowPos3dvARB, _gloffset_WindowPos3dvMESA ),
NAME_FUNC_OFFSET( 16761, glWindowPos3f, _gloffset_WindowPos3fMESA ),
NAME_FUNC_OFFSET( 16775, glWindowPos3fARB, _gloffset_WindowPos3fMESA ),
NAME_FUNC_OFFSET( 16792, glWindowPos3fv, _gloffset_WindowPos3fvMESA ),
NAME_FUNC_OFFSET( 16807, glWindowPos3fvARB, _gloffset_WindowPos3fvMESA ),
NAME_FUNC_OFFSET( 16825, glWindowPos3i, _gloffset_WindowPos3iMESA ),
NAME_FUNC_OFFSET( 16839, glWindowPos3iARB, _gloffset_WindowPos3iMESA ),
NAME_FUNC_OFFSET( 16856, glWindowPos3iv, _gloffset_WindowPos3ivMESA ),
NAME_FUNC_OFFSET( 16871, glWindowPos3ivARB, _gloffset_WindowPos3ivMESA ),
NAME_FUNC_OFFSET( 16889, glWindowPos3s, _gloffset_WindowPos3sMESA ),
NAME_FUNC_OFFSET( 16903, glWindowPos3sARB, _gloffset_WindowPos3sMESA ),
NAME_FUNC_OFFSET( 16920, glWindowPos3sv, _gloffset_WindowPos3svMESA ),
NAME_FUNC_OFFSET( 16935, glWindowPos3svARB, _gloffset_WindowPos3svMESA ),
NAME_FUNC_OFFSET( 16953, glBlendFuncSeparate, _gloffset_BlendFuncSeparateEXT ),
NAME_FUNC_OFFSET( 16973, glBlendFuncSeparateINGR, _gloffset_BlendFuncSeparateEXT ),
NAME_FUNC_OFFSET( 16997, glFogCoordf, _gloffset_FogCoordfEXT ),
NAME_FUNC_OFFSET( 17009, glFogCoordfv, _gloffset_FogCoordfvEXT ),
NAME_FUNC_OFFSET( 17022, glFogCoordd, _gloffset_FogCoorddEXT ),
NAME_FUNC_OFFSET( 17034, glFogCoorddv, _gloffset_FogCoorddvEXT ),
NAME_FUNC_OFFSET( 17047, glFogCoordPointer, _gloffset_FogCoordPointerEXT ),
NAME_FUNC_OFFSET( 17065, glCompressedTexImage3D, _gloffset_CompressedTexImage3DARB ),
NAME_FUNC_OFFSET( 17088, glCompressedTexImage2D, _gloffset_CompressedTexImage2DARB ),
NAME_FUNC_OFFSET( 17111, glCompressedTexImage1D, _gloffset_CompressedTexImage1DARB ),
NAME_FUNC_OFFSET( 17134, glCompressedTexSubImage3D, _gloffset_CompressedTexSubImage3DARB ),
NAME_FUNC_OFFSET( 17160, glCompressedTexSubImage2D, _gloffset_CompressedTexSubImage2DARB ),
NAME_FUNC_OFFSET( 17186, glCompressedTexSubImage1D, _gloffset_CompressedTexSubImage1DARB ),
NAME_FUNC_OFFSET( 17212, glGetCompressedTexImage, _gloffset_GetCompressedTexImageARB ),
NAME_FUNC_OFFSET( 17236, glSecondaryColor3b, _gloffset_SecondaryColor3bEXT ),
NAME_FUNC_OFFSET( 17255, glSecondaryColor3bv, _gloffset_SecondaryColor3bvEXT ),
NAME_FUNC_OFFSET( 17275, glSecondaryColor3d, _gloffset_SecondaryColor3dEXT ),
NAME_FUNC_OFFSET( 17294, glSecondaryColor3dv, _gloffset_SecondaryColor3dvEXT ),
NAME_FUNC_OFFSET( 17314, glSecondaryColor3f, _gloffset_SecondaryColor3fEXT ),
NAME_FUNC_OFFSET( 17333, glSecondaryColor3fv, _gloffset_SecondaryColor3fvEXT ),
NAME_FUNC_OFFSET( 17353, glSecondaryColor3i, _gloffset_SecondaryColor3iEXT ),
NAME_FUNC_OFFSET( 17372, glSecondaryColor3iv, _gloffset_SecondaryColor3ivEXT ),
NAME_FUNC_OFFSET( 17392, glSecondaryColor3s, _gloffset_SecondaryColor3sEXT ),
NAME_FUNC_OFFSET( 17411, glSecondaryColor3sv, _gloffset_SecondaryColor3svEXT ),
NAME_FUNC_OFFSET( 17431, glSecondaryColor3ub, _gloffset_SecondaryColor3ubEXT ),
NAME_FUNC_OFFSET( 17451, glSecondaryColor3ubv, _gloffset_SecondaryColor3ubvEXT ),
NAME_FUNC_OFFSET( 17472, glSecondaryColor3ui, _gloffset_SecondaryColor3uiEXT ),
NAME_FUNC_OFFSET( 17492, glSecondaryColor3uiv, _gloffset_SecondaryColor3uivEXT ),
NAME_FUNC_OFFSET( 17513, glSecondaryColor3us, _gloffset_SecondaryColor3usEXT ),
NAME_FUNC_OFFSET( 17533, glSecondaryColor3usv, _gloffset_SecondaryColor3usvEXT ),
NAME_FUNC_OFFSET( 17554, glSecondaryColorPointer, _gloffset_SecondaryColorPointerEXT ),
NAME_FUNC_OFFSET( 17578, glBindProgramARB, _gloffset_BindProgramNV ),
NAME_FUNC_OFFSET( 17595, glDeleteProgramsARB, _gloffset_DeleteProgramsNV ),
NAME_FUNC_OFFSET( 17615, glGenProgramsARB, _gloffset_GenProgramsNV ),
NAME_FUNC_OFFSET( 17632, glGetVertexAttribPointervARB, _gloffset_GetVertexAttribPointervNV ),
NAME_FUNC_OFFSET( 17661, glIsProgramARB, _gloffset_IsProgramNV ),
NAME_FUNC_OFFSET( 17676, glPointParameteri, _gloffset_PointParameteriNV ),
NAME_FUNC_OFFSET( 17694, glPointParameteriv, _gloffset_PointParameterivNV ),
NAME_FUNC_OFFSET( 17713, glMultiDrawArrays, _gloffset_MultiDrawArraysEXT ),
NAME_FUNC_OFFSET( 17731, glMultiDrawElements, _gloffset_MultiDrawElementsEXT ),
NAME_FUNC_OFFSET( 17751, glBindBuffer, _gloffset_BindBufferARB ),
NAME_FUNC_OFFSET( 17764, glBufferData, _gloffset_BufferDataARB ),
NAME_FUNC_OFFSET( 17777, glBufferSubData, _gloffset_BufferSubDataARB ),
NAME_FUNC_OFFSET( 17793, glDeleteBuffers, _gloffset_DeleteBuffersARB ),
NAME_FUNC_OFFSET( 17809, glGenBuffers, _gloffset_GenBuffersARB ),
NAME_FUNC_OFFSET( 17822, glGetBufferParameteriv, _gloffset_GetBufferParameterivARB ),
NAME_FUNC_OFFSET( 17845, glGetBufferPointerv, _gloffset_GetBufferPointervARB ),
NAME_FUNC_OFFSET( 17865, glGetBufferSubData, _gloffset_GetBufferSubDataARB ),
NAME_FUNC_OFFSET( 17884, glIsBuffer, _gloffset_IsBufferARB ),
NAME_FUNC_OFFSET( 17895, glMapBuffer, _gloffset_MapBufferARB ),
NAME_FUNC_OFFSET( 17907, glUnmapBuffer, _gloffset_UnmapBufferARB ),
NAME_FUNC_OFFSET( 17921, glGenQueries, _gloffset_GenQueriesARB ),
NAME_FUNC_OFFSET( 17934, glDeleteQueries, _gloffset_DeleteQueriesARB ),
NAME_FUNC_OFFSET( 17950, glIsQuery, _gloffset_IsQueryARB ),
NAME_FUNC_OFFSET( 17960, glBeginQuery, _gloffset_BeginQueryARB ),
NAME_FUNC_OFFSET( 17973, glEndQuery, _gloffset_EndQueryARB ),
NAME_FUNC_OFFSET( 17984, glGetQueryiv, _gloffset_GetQueryivARB ),
NAME_FUNC_OFFSET( 17997, glGetQueryObjectiv, _gloffset_GetQueryObjectivARB ),
NAME_FUNC_OFFSET( 18016, glGetQueryObjectuiv, _gloffset_GetQueryObjectuivARB ),
NAME_FUNC_OFFSET( 18036, glBlendEquationSeparateATI, _gloffset_BlendEquationSeparateEXT ),
NAME_FUNC_OFFSET( 14720, glBlitFramebufferEXT, _gloffset_BlitFramebufferEXT ),
NAME_FUNC_OFFSET( 14741, glArrayElementEXT, _gloffset_ArrayElement ),
NAME_FUNC_OFFSET( 14759, glBindTextureEXT, _gloffset_BindTexture ),
NAME_FUNC_OFFSET( 14776, glDrawArraysEXT, _gloffset_DrawArrays ),
NAME_FUNC_OFFSET( 14792, glCopyTexImage1DEXT, _gloffset_CopyTexImage1D ),
NAME_FUNC_OFFSET( 14812, glCopyTexImage2DEXT, _gloffset_CopyTexImage2D ),
NAME_FUNC_OFFSET( 14832, glCopyTexSubImage1DEXT, _gloffset_CopyTexSubImage1D ),
NAME_FUNC_OFFSET( 14855, glCopyTexSubImage2DEXT, _gloffset_CopyTexSubImage2D ),
NAME_FUNC_OFFSET( 14878, glDeleteTexturesEXT, _gloffset_DeleteTextures ),
NAME_FUNC_OFFSET( 14898, glGetPointervEXT, _gloffset_GetPointerv ),
NAME_FUNC_OFFSET( 14915, glPrioritizeTexturesEXT, _gloffset_PrioritizeTextures ),
NAME_FUNC_OFFSET( 14939, glTexSubImage1DEXT, _gloffset_TexSubImage1D ),
NAME_FUNC_OFFSET( 14958, glTexSubImage2DEXT, _gloffset_TexSubImage2D ),
NAME_FUNC_OFFSET( 14977, glBlendColorEXT, _gloffset_BlendColor ),
NAME_FUNC_OFFSET( 14993, glBlendEquationEXT, _gloffset_BlendEquation ),
NAME_FUNC_OFFSET( 15012, glDrawRangeElementsEXT, _gloffset_DrawRangeElements ),
NAME_FUNC_OFFSET( 15035, glColorTableSGI, _gloffset_ColorTable ),
NAME_FUNC_OFFSET( 15051, glColorTableEXT, _gloffset_ColorTable ),
NAME_FUNC_OFFSET( 15067, glColorTableParameterfvSGI, _gloffset_ColorTableParameterfv ),
NAME_FUNC_OFFSET( 15094, glColorTableParameterivSGI, _gloffset_ColorTableParameteriv ),
NAME_FUNC_OFFSET( 15121, glCopyColorTableSGI, _gloffset_CopyColorTable ),
NAME_FUNC_OFFSET( 15141, glColorSubTableEXT, _gloffset_ColorSubTable ),
NAME_FUNC_OFFSET( 15160, glCopyColorSubTableEXT, _gloffset_CopyColorSubTable ),
NAME_FUNC_OFFSET( 15183, glConvolutionFilter1DEXT, _gloffset_ConvolutionFilter1D ),
NAME_FUNC_OFFSET( 15208, glConvolutionFilter2DEXT, _gloffset_ConvolutionFilter2D ),
NAME_FUNC_OFFSET( 15233, glConvolutionParameterfEXT, _gloffset_ConvolutionParameterf ),
NAME_FUNC_OFFSET( 15260, glConvolutionParameterfvEXT, _gloffset_ConvolutionParameterfv ),
NAME_FUNC_OFFSET( 15288, glConvolutionParameteriEXT, _gloffset_ConvolutionParameteri ),
NAME_FUNC_OFFSET( 15315, glConvolutionParameterivEXT, _gloffset_ConvolutionParameteriv ),
NAME_FUNC_OFFSET( 15343, glCopyConvolutionFilter1DEXT, _gloffset_CopyConvolutionFilter1D ),
NAME_FUNC_OFFSET( 15372, glCopyConvolutionFilter2DEXT, _gloffset_CopyConvolutionFilter2D ),
NAME_FUNC_OFFSET( 15401, glSeparableFilter2DEXT, _gloffset_SeparableFilter2D ),
NAME_FUNC_OFFSET( 15424, glHistogramEXT, _gloffset_Histogram ),
NAME_FUNC_OFFSET( 15439, glMinmaxEXT, _gloffset_Minmax ),
NAME_FUNC_OFFSET( 15451, glResetHistogramEXT, _gloffset_ResetHistogram ),
NAME_FUNC_OFFSET( 15471, glResetMinmaxEXT, _gloffset_ResetMinmax ),
NAME_FUNC_OFFSET( 15488, glTexImage3DEXT, _gloffset_TexImage3D ),
NAME_FUNC_OFFSET( 15504, glTexSubImage3DEXT, _gloffset_TexSubImage3D ),
NAME_FUNC_OFFSET( 15523, glCopyTexSubImage3DEXT, _gloffset_CopyTexSubImage3D ),
NAME_FUNC_OFFSET( 15546, glActiveTexture, _gloffset_ActiveTextureARB ),
NAME_FUNC_OFFSET( 15562, glClientActiveTexture, _gloffset_ClientActiveTextureARB ),
NAME_FUNC_OFFSET( 15584, glMultiTexCoord1d, _gloffset_MultiTexCoord1dARB ),
NAME_FUNC_OFFSET( 15602, glMultiTexCoord1dv, _gloffset_MultiTexCoord1dvARB ),
NAME_FUNC_OFFSET( 15621, glMultiTexCoord1f, _gloffset_MultiTexCoord1fARB ),
NAME_FUNC_OFFSET( 15639, glMultiTexCoord1fv, _gloffset_MultiTexCoord1fvARB ),
NAME_FUNC_OFFSET( 15658, glMultiTexCoord1i, _gloffset_MultiTexCoord1iARB ),
NAME_FUNC_OFFSET( 15676, glMultiTexCoord1iv, _gloffset_MultiTexCoord1ivARB ),
NAME_FUNC_OFFSET( 15695, glMultiTexCoord1s, _gloffset_MultiTexCoord1sARB ),
NAME_FUNC_OFFSET( 15713, glMultiTexCoord1sv, _gloffset_MultiTexCoord1svARB ),
NAME_FUNC_OFFSET( 15732, glMultiTexCoord2d, _gloffset_MultiTexCoord2dARB ),
NAME_FUNC_OFFSET( 15750, glMultiTexCoord2dv, _gloffset_MultiTexCoord2dvARB ),
NAME_FUNC_OFFSET( 15769, glMultiTexCoord2f, _gloffset_MultiTexCoord2fARB ),
NAME_FUNC_OFFSET( 15787, glMultiTexCoord2fv, _gloffset_MultiTexCoord2fvARB ),
NAME_FUNC_OFFSET( 15806, glMultiTexCoord2i, _gloffset_MultiTexCoord2iARB ),
NAME_FUNC_OFFSET( 15824, glMultiTexCoord2iv, _gloffset_MultiTexCoord2ivARB ),
NAME_FUNC_OFFSET( 15843, glMultiTexCoord2s, _gloffset_MultiTexCoord2sARB ),
NAME_FUNC_OFFSET( 15861, glMultiTexCoord2sv, _gloffset_MultiTexCoord2svARB ),
NAME_FUNC_OFFSET( 15880, glMultiTexCoord3d, _gloffset_MultiTexCoord3dARB ),
NAME_FUNC_OFFSET( 15898, glMultiTexCoord3dv, _gloffset_MultiTexCoord3dvARB ),
NAME_FUNC_OFFSET( 15917, glMultiTexCoord3f, _gloffset_MultiTexCoord3fARB ),
NAME_FUNC_OFFSET( 15935, glMultiTexCoord3fv, _gloffset_MultiTexCoord3fvARB ),
NAME_FUNC_OFFSET( 15954, glMultiTexCoord3i, _gloffset_MultiTexCoord3iARB ),
NAME_FUNC_OFFSET( 15972, glMultiTexCoord3iv, _gloffset_MultiTexCoord3ivARB ),
NAME_FUNC_OFFSET( 15991, glMultiTexCoord3s, _gloffset_MultiTexCoord3sARB ),
NAME_FUNC_OFFSET( 16009, glMultiTexCoord3sv, _gloffset_MultiTexCoord3svARB ),
NAME_FUNC_OFFSET( 16028, glMultiTexCoord4d, _gloffset_MultiTexCoord4dARB ),
NAME_FUNC_OFFSET( 16046, glMultiTexCoord4dv, _gloffset_MultiTexCoord4dvARB ),
NAME_FUNC_OFFSET( 16065, glMultiTexCoord4f, _gloffset_MultiTexCoord4fARB ),
NAME_FUNC_OFFSET( 16083, glMultiTexCoord4fv, _gloffset_MultiTexCoord4fvARB ),
NAME_FUNC_OFFSET( 16102, glMultiTexCoord4i, _gloffset_MultiTexCoord4iARB ),
NAME_FUNC_OFFSET( 16120, glMultiTexCoord4iv, _gloffset_MultiTexCoord4ivARB ),
NAME_FUNC_OFFSET( 16139, glMultiTexCoord4s, _gloffset_MultiTexCoord4sARB ),
NAME_FUNC_OFFSET( 16157, glMultiTexCoord4sv, _gloffset_MultiTexCoord4svARB ),
NAME_FUNC_OFFSET( 16176, glLoadTransposeMatrixf, _gloffset_LoadTransposeMatrixfARB ),
NAME_FUNC_OFFSET( 16199, glLoadTransposeMatrixd, _gloffset_LoadTransposeMatrixdARB ),
NAME_FUNC_OFFSET( 16222, glMultTransposeMatrixf, _gloffset_MultTransposeMatrixfARB ),
NAME_FUNC_OFFSET( 16245, glMultTransposeMatrixd, _gloffset_MultTransposeMatrixdARB ),
NAME_FUNC_OFFSET( 16268, glSampleCoverage, _gloffset_SampleCoverageARB ),
NAME_FUNC_OFFSET( 16285, glDrawBuffersATI, _gloffset_DrawBuffersARB ),
NAME_FUNC_OFFSET( 16302, glSampleMaskEXT, _gloffset_SampleMaskSGIS ),
NAME_FUNC_OFFSET( 16318, glSamplePatternEXT, _gloffset_SamplePatternSGIS ),
NAME_FUNC_OFFSET( 16337, glPointParameterf, _gloffset_PointParameterfEXT ),
NAME_FUNC_OFFSET( 16355, glPointParameterfARB, _gloffset_PointParameterfEXT ),
NAME_FUNC_OFFSET( 16376, glPointParameterfSGIS, _gloffset_PointParameterfEXT ),
NAME_FUNC_OFFSET( 16398, glPointParameterfv, _gloffset_PointParameterfvEXT ),
NAME_FUNC_OFFSET( 16417, glPointParameterfvARB, _gloffset_PointParameterfvEXT ),
NAME_FUNC_OFFSET( 16439, glPointParameterfvSGIS, _gloffset_PointParameterfvEXT ),
NAME_FUNC_OFFSET( 16462, glWindowPos2d, _gloffset_WindowPos2dMESA ),
NAME_FUNC_OFFSET( 16476, glWindowPos2dARB, _gloffset_WindowPos2dMESA ),
NAME_FUNC_OFFSET( 16493, glWindowPos2dv, _gloffset_WindowPos2dvMESA ),
NAME_FUNC_OFFSET( 16508, glWindowPos2dvARB, _gloffset_WindowPos2dvMESA ),
NAME_FUNC_OFFSET( 16526, glWindowPos2f, _gloffset_WindowPos2fMESA ),
NAME_FUNC_OFFSET( 16540, glWindowPos2fARB, _gloffset_WindowPos2fMESA ),
NAME_FUNC_OFFSET( 16557, glWindowPos2fv, _gloffset_WindowPos2fvMESA ),
NAME_FUNC_OFFSET( 16572, glWindowPos2fvARB, _gloffset_WindowPos2fvMESA ),
NAME_FUNC_OFFSET( 16590, glWindowPos2i, _gloffset_WindowPos2iMESA ),
NAME_FUNC_OFFSET( 16604, glWindowPos2iARB, _gloffset_WindowPos2iMESA ),
NAME_FUNC_OFFSET( 16621, glWindowPos2iv, _gloffset_WindowPos2ivMESA ),
NAME_FUNC_OFFSET( 16636, glWindowPos2ivARB, _gloffset_WindowPos2ivMESA ),
NAME_FUNC_OFFSET( 16654, glWindowPos2s, _gloffset_WindowPos2sMESA ),
NAME_FUNC_OFFSET( 16668, glWindowPos2sARB, _gloffset_WindowPos2sMESA ),
NAME_FUNC_OFFSET( 16685, glWindowPos2sv, _gloffset_WindowPos2svMESA ),
NAME_FUNC_OFFSET( 16700, glWindowPos2svARB, _gloffset_WindowPos2svMESA ),
NAME_FUNC_OFFSET( 16718, glWindowPos3d, _gloffset_WindowPos3dMESA ),
NAME_FUNC_OFFSET( 16732, glWindowPos3dARB, _gloffset_WindowPos3dMESA ),
NAME_FUNC_OFFSET( 16749, glWindowPos3dv, _gloffset_WindowPos3dvMESA ),
NAME_FUNC_OFFSET( 16764, glWindowPos3dvARB, _gloffset_WindowPos3dvMESA ),
NAME_FUNC_OFFSET( 16782, glWindowPos3f, _gloffset_WindowPos3fMESA ),
NAME_FUNC_OFFSET( 16796, glWindowPos3fARB, _gloffset_WindowPos3fMESA ),
NAME_FUNC_OFFSET( 16813, glWindowPos3fv, _gloffset_WindowPos3fvMESA ),
NAME_FUNC_OFFSET( 16828, glWindowPos3fvARB, _gloffset_WindowPos3fvMESA ),
NAME_FUNC_OFFSET( 16846, glWindowPos3i, _gloffset_WindowPos3iMESA ),
NAME_FUNC_OFFSET( 16860, glWindowPos3iARB, _gloffset_WindowPos3iMESA ),
NAME_FUNC_OFFSET( 16877, glWindowPos3iv, _gloffset_WindowPos3ivMESA ),
NAME_FUNC_OFFSET( 16892, glWindowPos3ivARB, _gloffset_WindowPos3ivMESA ),
NAME_FUNC_OFFSET( 16910, glWindowPos3s, _gloffset_WindowPos3sMESA ),
NAME_FUNC_OFFSET( 16924, glWindowPos3sARB, _gloffset_WindowPos3sMESA ),
NAME_FUNC_OFFSET( 16941, glWindowPos3sv, _gloffset_WindowPos3svMESA ),
NAME_FUNC_OFFSET( 16956, glWindowPos3svARB, _gloffset_WindowPos3svMESA ),
NAME_FUNC_OFFSET( 16974, glBlendFuncSeparate, _gloffset_BlendFuncSeparateEXT ),
NAME_FUNC_OFFSET( 16994, glBlendFuncSeparateINGR, _gloffset_BlendFuncSeparateEXT ),
NAME_FUNC_OFFSET( 17018, glFogCoordf, _gloffset_FogCoordfEXT ),
NAME_FUNC_OFFSET( 17030, glFogCoordfv, _gloffset_FogCoordfvEXT ),
NAME_FUNC_OFFSET( 17043, glFogCoordd, _gloffset_FogCoorddEXT ),
NAME_FUNC_OFFSET( 17055, glFogCoorddv, _gloffset_FogCoorddvEXT ),
NAME_FUNC_OFFSET( 17068, glFogCoordPointer, _gloffset_FogCoordPointerEXT ),
NAME_FUNC_OFFSET( 17086, glCompressedTexImage3D, _gloffset_CompressedTexImage3DARB ),
NAME_FUNC_OFFSET( 17109, glCompressedTexImage2D, _gloffset_CompressedTexImage2DARB ),
NAME_FUNC_OFFSET( 17132, glCompressedTexImage1D, _gloffset_CompressedTexImage1DARB ),
NAME_FUNC_OFFSET( 17155, glCompressedTexSubImage3D, _gloffset_CompressedTexSubImage3DARB ),
NAME_FUNC_OFFSET( 17181, glCompressedTexSubImage2D, _gloffset_CompressedTexSubImage2DARB ),
NAME_FUNC_OFFSET( 17207, glCompressedTexSubImage1D, _gloffset_CompressedTexSubImage1DARB ),
NAME_FUNC_OFFSET( 17233, glGetCompressedTexImage, _gloffset_GetCompressedTexImageARB ),
NAME_FUNC_OFFSET( 17257, glSecondaryColor3b, _gloffset_SecondaryColor3bEXT ),
NAME_FUNC_OFFSET( 17276, glSecondaryColor3bv, _gloffset_SecondaryColor3bvEXT ),
NAME_FUNC_OFFSET( 17296, glSecondaryColor3d, _gloffset_SecondaryColor3dEXT ),
NAME_FUNC_OFFSET( 17315, glSecondaryColor3dv, _gloffset_SecondaryColor3dvEXT ),
NAME_FUNC_OFFSET( 17335, glSecondaryColor3f, _gloffset_SecondaryColor3fEXT ),
NAME_FUNC_OFFSET( 17354, glSecondaryColor3fv, _gloffset_SecondaryColor3fvEXT ),
NAME_FUNC_OFFSET( 17374, glSecondaryColor3i, _gloffset_SecondaryColor3iEXT ),
NAME_FUNC_OFFSET( 17393, glSecondaryColor3iv, _gloffset_SecondaryColor3ivEXT ),
NAME_FUNC_OFFSET( 17413, glSecondaryColor3s, _gloffset_SecondaryColor3sEXT ),
NAME_FUNC_OFFSET( 17432, glSecondaryColor3sv, _gloffset_SecondaryColor3svEXT ),
NAME_FUNC_OFFSET( 17452, glSecondaryColor3ub, _gloffset_SecondaryColor3ubEXT ),
NAME_FUNC_OFFSET( 17472, glSecondaryColor3ubv, _gloffset_SecondaryColor3ubvEXT ),
NAME_FUNC_OFFSET( 17493, glSecondaryColor3ui, _gloffset_SecondaryColor3uiEXT ),
NAME_FUNC_OFFSET( 17513, glSecondaryColor3uiv, _gloffset_SecondaryColor3uivEXT ),
NAME_FUNC_OFFSET( 17534, glSecondaryColor3us, _gloffset_SecondaryColor3usEXT ),
NAME_FUNC_OFFSET( 17554, glSecondaryColor3usv, _gloffset_SecondaryColor3usvEXT ),
NAME_FUNC_OFFSET( 17575, glSecondaryColorPointer, _gloffset_SecondaryColorPointerEXT ),
NAME_FUNC_OFFSET( 17599, glBindProgramARB, _gloffset_BindProgramNV ),
NAME_FUNC_OFFSET( 17616, glDeleteProgramsARB, _gloffset_DeleteProgramsNV ),
NAME_FUNC_OFFSET( 17636, glGenProgramsARB, _gloffset_GenProgramsNV ),
NAME_FUNC_OFFSET( 17653, glGetVertexAttribPointervARB, _gloffset_GetVertexAttribPointervNV ),
NAME_FUNC_OFFSET( 17682, glIsProgramARB, _gloffset_IsProgramNV ),
NAME_FUNC_OFFSET( 17697, glPointParameteri, _gloffset_PointParameteriNV ),
NAME_FUNC_OFFSET( 17715, glPointParameteriv, _gloffset_PointParameterivNV ),
NAME_FUNC_OFFSET( 17734, glMultiDrawArrays, _gloffset_MultiDrawArraysEXT ),
NAME_FUNC_OFFSET( 17752, glMultiDrawElements, _gloffset_MultiDrawElementsEXT ),
NAME_FUNC_OFFSET( 17772, glBindBuffer, _gloffset_BindBufferARB ),
NAME_FUNC_OFFSET( 17785, glBufferData, _gloffset_BufferDataARB ),
NAME_FUNC_OFFSET( 17798, glBufferSubData, _gloffset_BufferSubDataARB ),
NAME_FUNC_OFFSET( 17814, glDeleteBuffers, _gloffset_DeleteBuffersARB ),
NAME_FUNC_OFFSET( 17830, glGenBuffers, _gloffset_GenBuffersARB ),
NAME_FUNC_OFFSET( 17843, glGetBufferParameteriv, _gloffset_GetBufferParameterivARB ),
NAME_FUNC_OFFSET( 17866, glGetBufferPointerv, _gloffset_GetBufferPointervARB ),
NAME_FUNC_OFFSET( 17886, glGetBufferSubData, _gloffset_GetBufferSubDataARB ),
NAME_FUNC_OFFSET( 17905, glIsBuffer, _gloffset_IsBufferARB ),
NAME_FUNC_OFFSET( 17916, glMapBuffer, _gloffset_MapBufferARB ),
NAME_FUNC_OFFSET( 17928, glUnmapBuffer, _gloffset_UnmapBufferARB ),
NAME_FUNC_OFFSET( 17942, glGenQueries, _gloffset_GenQueriesARB ),
NAME_FUNC_OFFSET( 17955, glDeleteQueries, _gloffset_DeleteQueriesARB ),
NAME_FUNC_OFFSET( 17971, glIsQuery, _gloffset_IsQueryARB ),
NAME_FUNC_OFFSET( 17981, glBeginQuery, _gloffset_BeginQueryARB ),
NAME_FUNC_OFFSET( 17994, glEndQuery, _gloffset_EndQueryARB ),
NAME_FUNC_OFFSET( 18005, glGetQueryiv, _gloffset_GetQueryivARB ),
NAME_FUNC_OFFSET( 18018, glGetQueryObjectiv, _gloffset_GetQueryObjectivARB ),
NAME_FUNC_OFFSET( 18037, glGetQueryObjectuiv, _gloffset_GetQueryObjectuivARB ),
NAME_FUNC_OFFSET( 18057, glBlendEquationSeparateATI, _gloffset_BlendEquationSeparateEXT ),
NAME_FUNC_OFFSET( -1, NULL, 0 )
};

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python
# $Id: mesadef.py,v 1.3 2005/09/05 14:09:25 kschultz Exp $
# $Id: mesadef.py,v 1.3.2.1 2006/03/25 23:48:21 brianp Exp $
# Mesa 3-D graphics library
# Version: 4.1
@@ -89,6 +89,7 @@ def PrintTail():
print '\twglDescribePixelFormat'
print '\twglGetCurrentContext'
print '\twglGetCurrentDC'
print '\twglGetExtensionsStringARB'
print '\twglGetLayerPaletteEntries'
print '\twglGetPixelFormat'
print '\twglGetProcAddress'

View File

@@ -29,20 +29,21 @@ import string, copy
class type_node:
def __init__(self):
self.pointer = 0
self.const = 0
self.signed = 1
self.integer = 1
self.pointer = 0 # bool
self.const = 0 # bool
self.signed = 1 # bool
self.integer = 1 # bool
# If elements is set to non-zero, then field is an array.
self.elements = 0
self.name = None
self.size = 0
self.size = 0 # type's size in bytes
return
def string(self):
"""Return string representation of this type_node."""
s = ""
if self.pointer:
@@ -85,16 +86,17 @@ class type_table:
def create_initial_types():
tt = type_table()
basic_types = [ ["char", 1, 1], \
["short", 2, 1], \
["int", 4, 1], \
["long", 4, 1], \
["float", 4, 0], \
["double", 8, 0], \
["enum", 4, 1] ]
basic_types = [
("char", 1, 1),
("short", 2, 1),
("int", 4, 1),
("long", 4, 1),
("float", 4, 0),
("double", 8, 0),
("enum", 4, 1)
]
for [type_name, type_size, integer] in basic_types:
for (type_name, type_size, integer) in basic_types:
te = type_expression(None)
tn = type_node()
tn.name = type_name
@@ -113,22 +115,24 @@ class type_expression:
def __init__(self, type_string, extra_types = None):
self.expr = []
if not type_string: return
if not type_string:
return
self.original_string = type_string
if not type_expression.built_in_types:
raise RuntimeError("create_initial_types must be called before creating type_expression objects.")
elements = string.split( string.replace( type_string, "*", " * " ) )
# Replace '*' with ' * ' in type_string. Then, split the string
# into tokens, separated by spaces.
tokens = string.split( string.replace( type_string, "*", " * " ) )
const = 0
t = None
signed = 0
unsigned = 0
for i in elements:
for i in tokens:
if i == "const":
if t and t.pointer:
t.const = 1

Some files were not shown because too many files have changed in this diff Show More