aboutsummaryrefslogtreecommitdiff
path: root/pixman/pixman/refactor
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/pixman/refactor')
-rw-r--r--pixman/pixman/refactor478
1 files changed, 478 insertions, 0 deletions
diff --git a/pixman/pixman/refactor b/pixman/pixman/refactor
new file mode 100644
index 000000000..b93b75c08
--- /dev/null
+++ b/pixman/pixman/refactor
@@ -0,0 +1,478 @@
+Roadmap
+
+- Move all the fetchers etc. into pixman-image to make pixman-compose.c
+ less intimidating.
+
+ DONE
+
+- Make combiners for unified alpha take a mask argument. That way
+ we won't need two separate paths for unified vs component in the
+ general compositing code.
+
+ DONE, except that the Altivec code needs to be updated. Luca is
+ looking into that.
+
+- Delete separate 'unified alpha' path
+
+ DONE
+
+- Split images into their own files
+
+ DONE
+
+- Split the gradient walker code out into its own file
+
+ DONE
+
+- Add scanline getters per image
+
+ DONE
+
+- Generic 64 bit fetcher
+
+ DONE
+
+- Split fast path tables into their respective architecture dependent
+ files.
+
+See "Render Algorithm" below for rationale
+
+Images will eventually have these virtual functions:
+
+ get_scanline()
+ get_scanline_wide()
+ get_pixel()
+ get_pixel_wide()
+ get_untransformed_pixel()
+ get_untransformed_pixel_wide()
+ get_unfiltered_pixel()
+ get_unfiltered_pixel_wide()
+
+ store_scanline()
+ store_scanline_wide()
+
+1.
+
+Initially we will just have get_scanline() and get_scanline_wide();
+these will be based on the ones in pixman-compose. Hopefully this will
+reduce the complexity in pixman_composite_rect_general().
+
+Note that there is access considerations - the compose function is
+being compiled twice.
+
+
+2.
+
+Split image types into their own source files. Export noop virtual
+reinit() call. Call this whenever a property of the image changes.
+
+
+3.
+
+Split the get_scanline() call into smaller functions that are
+initialized by the reinit() call.
+
+The Render Algorithm:
+ (first repeat, then filter, then transform, then clip)
+
+Starting from a destination pixel (x, y), do
+
+ 1 x = x - xDst + xSrc
+ y = y - yDst + ySrc
+
+ 2 reject pixel that is outside the clip
+
+ This treats clipping as something that happens after
+ transformation, which I think is correct for client clips. For
+ hierarchy clips it is wrong, but who really cares? Without
+ GraphicsExposes hierarchy clips are basically irrelevant. Yes,
+ you could imagine cases where the pixels of a subwindow of a
+ redirected, transformed window should be treated as
+ transparent. I don't really care
+
+ Basically, I think the render spec should say that pixels that
+ are unavailable due to the hierarcy have undefined content,
+ and that GraphicsExposes are not generated. Ie., basically
+ that using non-redirected windows as sources is fail. This is
+ at least consistent with the current implementation and we can
+ update the spec later if someone makes it work.
+
+ The implication for render is that it should stop passing the
+ hierarchy clip to pixman. In pixman, if a souce image has a
+ clip it should be used in computing the composite region and
+ nowhere else, regardless of what "has_client_clip" says. The
+ default should be for there to not be any clip.
+
+ I would really like to get rid of the client clip as well for
+ source images, but unfortunately there is at least one
+ application in the wild that uses them.
+
+ 3 Transform pixel: (x, y) = T(x, y)
+
+ 4 Call p = GetUntransformedPixel (x, y)
+
+ 5 If the image has an alpha map, then
+
+ Call GetUntransformedPixel (x, y) on the alpha map
+
+ add resulting alpha channel to p
+
+ return p
+
+ Where GetUnTransformedPixel is:
+
+ 6 switch (filter)
+ {
+ case NEAREST:
+ return GetUnfilteredPixel (x, y);
+ break;
+
+ case BILINEAR:
+ return GetUnfilteredPixel (...) // 4 times
+ break;
+
+ case CONVOLUTION:
+ return GetUnfilteredPixel (...) // as many times as necessary.
+ break;
+ }
+
+ Where GetUnfilteredPixel (x, y) is
+
+ 7 switch (repeat)
+ {
+ case REPEAT_NORMAL:
+ case REPEAT_PAD:
+ case REPEAT_REFLECT:
+ // adjust x, y as appropriate
+ break;
+
+ case REPEAT_NONE:
+ if (x, y) is outside image bounds
+ return 0;
+ break;
+ }
+
+ return GetRawPixel(x, y)
+
+ Where GetRawPixel (x, y) is
+
+ 8 Compute the pixel in question, depending on image type.
+
+For gradients, repeat has a totally different meaning, so
+UnfilteredPixel() and RawPixel() must be the same function so that
+gradients can do their own repeat algorithm.
+
+So, the GetRawPixel
+
+ for bits must deal with repeats
+ for gradients must deal with repeats (differently)
+ for solids, should ignore repeats.
+
+ for polygons, when we add them, either ignore repeats or do
+ something similar to bits (in which case, we may want an extra
+ layer of indirection to modify the coordinates).
+
+It is then possible to build things like "get scanline" or "get tile" on
+top of this. In the simplest case, just repeatedly calling GetPixel()
+would work, but specialized get_scanline()s or get_tile()s could be
+plugged in for common cases.
+
+By not plugging anything in for images with access functions, we only
+have to compile the pixel functions twice, not the scanline functions.
+
+And we can get rid of fetchers for the bizarre formats that no one
+uses. Such as b2g3r3 etc. r1g2b1? Seriously? It is also worth
+considering a generic format based pixel fetcher for these edge cases.
+
+Since the actual routines depend on the image attributes, the images
+must be notified when those change and update their function pointers
+appropriately. So there should probably be a virtual function called
+(* reinit) or something like that.
+
+There will also be wide fetchers for both pixels and lines. The line
+fetcher will just call the wide pixel fetcher. The wide pixel fetcher
+will just call expand, except for 10 bit formats.
+
+Rendering pipeline:
+
+Drawable:
+ 0. if (picture has alpha map)
+ 0.1. Position alpha map according to the alpha_x/alpha_y
+ 0.2. Where the two drawables intersect, the alpha channel
+ Replace the alpha channel of source with the one
+ from the alpha map. Replacement only takes place
+ in the intersection of the two drawables' geometries.
+ 1. Repeat the drawable according to the repeat attribute
+ 2. Reconstruct a continuous image according to the filter
+ 3. Transform according to the transform attribute
+ 4. Position image such that src_x, src_y is over dst_x, dst_y
+ 5. Sample once per destination pixel
+ 6. Clip. If a pixel is not within the source clip, then no
+ compositing takes place at that pixel. (Ie., it's *not*
+ treated as 0).
+
+ Sampling a drawable:
+
+ - If the channel does not have an alpha channel, the pixels in it
+ are treated as opaque.
+
+ Note on reconstruction:
+
+ - The top left pixel has coordinates (0.5, 0.5) and pixels are
+ spaced 1 apart.
+
+Gradient:
+ 1. Unless gradient type is conical, repeat the underlying (0, 1)
+ gradient according to the repeat attribute
+ 2. Integrate the gradient across the plane according to type.
+ 3. Transform according to transform attribute
+ 4. Position gradient
+ 5. Sample once per destination pixel.
+ 6. Clip
+
+Solid Fill:
+ 1. Repeat has no effect
+ 2. Image is already continuous and defined for the entire plane
+ 3. Transform has no effect
+ 4. Positioning has no effect
+ 5. Sample once per destination pixel.
+ 6. Clip
+
+Polygon:
+ 1. Repeat has no effect
+ 2. Image is already continuous and defined on the whole plane
+ 3. Transform according to transform attribute
+ 4. Position image
+ 5. Supersample 15x17 per destination pixel.
+ 6. Clip
+
+Possibly interesting additions:
+ - More general transformations, such as warping, or general
+ shading.
+
+ - Shader image where a function is called to generate the
+ pixel (ie., uploading assembly code).
+
+ - Resampling kernels
+
+ In principle the polygon image uses a 15x17 box filter for
+ resampling. If we allow general resampling filters, then we
+ get all the various antialiasing types for free.
+
+ Bilinear downsampling looks terrible and could be much
+ improved by a resampling filter. NEAREST reconstruction
+ combined with a box resampling filter is what GdkPixbuf
+ does, I believe.
+
+ Useful for high frequency gradients as well.
+
+ (Note that the difference between a reconstruction and a
+ resampling filter is mainly where in the pipeline they
+ occur. High quality resampling should use a correctly
+ oriented kernel so it should happen after transformation.
+
+ An implementation can transform the resampling kernel and
+ convolve it with the reconstruction if it so desires, but it
+ will need to deal with the fact that the resampling kernel
+ will not necessarily be pixel aligned.
+
+ "Output kernels"
+
+ One could imagine doing the resampling after compositing,
+ ie., for each destination pixel sample each source image 16
+ times, then composite those subpixels individually, then
+ finally apply a kernel.
+
+ However, this is effectively the same as full screen
+ antialiasing, which is a simpler way to think about it. So
+ resampling kernels may make sense for individual images, but
+ not as a post-compositing step.
+
+ Fullscreen AA is inefficient without chained compositing
+ though. Consider an (image scaled up to oversample size IN
+ some polygon) scaled down to screen size. With the current
+ implementation, there will be a huge temporary. With chained
+ compositing, the whole thing ends up being equivalent to the
+ output kernel from above.
+
+ - Color space conversion
+
+ The complete model here is that each surface has a color
+ space associated with it and that the compositing operation
+ also has one associated with it. Note also that gradients
+ should have associcated colorspaces.
+
+ - Dithering
+
+ If people dither something that is already dithered, it will
+ look terrible, but don't do that, then. (Dithering happens
+ after resampling if at all - what is the relationship
+ with color spaces? Presumably dithering should happen in linear
+ intensity space).
+
+ - Floating point surfaces, 16, 32 and possibly 64 bit per
+ channel.
+
+ Maybe crack:
+
+ - Glyph polygons
+
+ If glyphs could be given as polygons, they could be
+ positioned and rasterized more accurately. The glyph
+ structure would need subpixel positioning though.
+
+ - Luminance vs. coverage for the alpha channel
+
+ Whether the alpha channel should be interpreted as luminance
+ modulation or as coverage (intensity modulation). This is a
+ bit of a departure from the rendering model though. It could
+ also be considered whether it should be possible to have
+ both channels in the same drawable.
+
+ - Alternative for component alpha
+
+ - Set component-alpha on the output image.
+
+ - This means each of the components are sampled
+ independently and composited in the corresponding
+ channel only.
+
+ - Have 3 x oversampled mask
+
+ - Scale it down by 3 horizontally, with [ 1/3, 1/3, 1/3 ]
+ resampling filter.
+
+ Is this equivalent to just using a component alpha mask?
+
+ Incompatible changes:
+
+ - Gradients could be specified with premultiplied colors. (You
+ can use a mask to get things like gradients from solid red to
+ transparent red.
+
+Refactoring pixman
+
+The pixman code is not particularly nice to put it mildly. Among the
+issues are
+
+- inconsistent naming style (fb vs Fb, camelCase vs
+ underscore_naming). Sometimes there is even inconsistency *within*
+ one name.
+
+ fetchProc32 ACCESS(pixman_fetchProcForPicture32)
+
+ may be one of the uglies names ever created.
+
+ coding style:
+ use the one from cairo except that pixman uses this brace style:
+
+ while (blah)
+ {
+ }
+
+ Format do while like this:
+
+ do
+ {
+
+ }
+ while (...);
+
+- PIXMAN_COMPOSITE_RECT_GENERAL() is horribly complex
+
+- switch case logic in pixman-access.c
+
+ Instead it would be better to just store function pointers in the
+ image objects themselves,
+
+ get_pixel()
+ get_scanline()
+
+- Much of the scanline fetching code is for formats that no one
+ ever uses. a2r2g2b2 anyone?
+
+ It would probably be worthwhile having a generic fetcher for any
+ pixman format whatsoever.
+
+- Code related to particular image types should be split into individual
+ files.
+
+ pixman-bits-image.c
+ pixman-linear-gradient-image.c
+ pixman-radial-gradient-image.c
+ pixman-solid-image.c
+
+- Fast path code should be split into files based on architecture:
+
+ pixman-mmx-fastpath.c
+ pixman-sse2-fastpath.c
+ pixman-c-fastpath.c
+
+ etc.
+
+ Each of these files should then export a fastpath table, which would
+ be declared in pixman-private.h. This should allow us to get rid
+ of the pixman-mmx.h files.
+
+ The fast path table should describe each fast path. Ie there should
+ be bitfields indicating what things the fast path can handle, rather than
+ like now where it is only allowed to take one format per src/mask/dest. Ie.,
+
+ {
+ FAST_a8r8g8b8 | FAST_x8r8g8b8,
+ FAST_null,
+ FAST_x8r8g8b8,
+ FAST_repeat_normal | FAST_repeat_none,
+ the_fast_path
+ }
+
+There should then be *one* file that implements pixman_image_composite().
+This should do this:
+
+ optimize_operator();
+
+ convert 1x1 repeat to solid (actually this should be done at
+ image creation time).
+
+ is there a useful fastpath?
+
+There should be a file called pixman-cpu.c that contains all the
+architecture specific stuff to detect what CPU features we have.
+
+Issues that must be kept in mind:
+
+ - we need accessor code to be preserved
+
+ - maybe there should be a "store_scanline" too?
+
+ Is this sufficient?
+
+ We should preserve the optimization where the
+ compositing happens directly in the destination
+ whenever possible.
+
+ - It should be possible to create GPU samplers from the
+ images.
+
+The "horizontal" classification should be a bit in the image, the
+"vertical" classification should just happen inside the gradient
+file. Note though that
+
+ (a) these will change if the tranformation/repeat changes.
+
+ (b) at the moment the optimization for linear gradients
+ takes the source rectangle into account. Presumably
+ this is to also optimize the case where the gradient
+ is close enough to horizontal?
+
+Who is responsible for repeats? In principle it should be the scanline
+fetch. Right now NORMAL repeats are handled by walk_composite_region()
+while other repeats are handled by the scanline code.
+
+
+(Random note on filtering: do you filter before or after
+transformation? Hardware is going to filter after transformation;
+this is also what pixman does currently). It's not completely clear
+what filtering *after* transformation means. One thing that might look
+good would be to do *supersampling*, ie., compute multiple subpixels
+per destination pixel, then average them together.