Summary: | Zero-width lines drawn differently than vesa driver (but consistent with line width 1) | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Product: | xorg | Reporter: | Bryce Harrington <bryce> | ||||||||||||||||||
Component: | Driver/intel | Assignee: | Carl Worth <cworth> | ||||||||||||||||||
Status: | RESOLVED INVALID | QA Contact: | Xorg Project Team <xorg-team> | ||||||||||||||||||
Severity: | normal | ||||||||||||||||||||
Priority: | low | CC: | jaimerave | ||||||||||||||||||
Version: | 7.4 (2008.09) | ||||||||||||||||||||
Hardware: | x86 (IA32) | ||||||||||||||||||||
OS: | Linux (All) | ||||||||||||||||||||
Whiteboard: | |||||||||||||||||||||
i915 platform: | i915 features: | ||||||||||||||||||||
Attachments: |
|
Description
Bryce Harrington
2009-07-14 15:44:58 UTC
Created attachment 27692 [details]
dialog img
Created attachment 27693 [details]
closeup img
Created attachment 27694 [details]
buttons img
(I'm dropping the priority on this a notch since it's a cosmetic issue, which apparently only affects wine. I think I set it too high when initially filed, apologies if you do think it should be major/high.) Hi Bryce, I have to agree that it's hard to prioritize this bug over things that cause lockups of the GPU or failure to login. But at the same time, I do have a part of me that is anxious to make every last pixel correct. :-) Jaime, I think what we'll need next is a smaller test case to help us know exactly what operation is resulting in the missing pixel. It's a bit too much for us as driver hackers to hear "wine dialog" and know what the problem might be. Could you perhaps do some investigation to find out as much as you can about what is actually being drawn here? Is it lines? Filled rectangles? Outlined rectangles? And how it's being drawn: Is wine using XDrawLines? XDrawRectangle? cairo calls? Ideally we could get this down to a single call, (say one XDrawLines request), where the vesa driver and the intel driver behave differently. If we had that, I would guess that it should be quite easy to identify and fix the bug. One very good approach to getting this information might be to run an X protocol capture tool and capture a trace. For example: xtrace & DISPLAY=:9 wine ./whatever/program/shows/the/bug There will be a lot of output, (but the more simple program you can use, the better of course). But hopefully by knowing where on the screen the missing pixel is, you can grep through the trace and find where the problem is. Oh, another thing you might try is to instead run "xtrace -i" in a separate terminal rather than running it in the background. This puts xtrace into an "interactive" mode where you have to press Enter before it forwards each request. This way you can control how slowly the application runs and know when the right range of output is appearing in the protocol trace. I hope that helps and that we can track down your missing pixel for you. -Carl Well I've made some researching, I'm not a XServer guru but this is what I found using xtrace. When is going to draw the button (that shows the bug) in a example program this is the code that is been called. 001:<:0119: 20: Request(59): SetClipRectangles ordering=YXBanded(0x03) gc=0x0560000b clip-x-origin=36 clip-y-origin=16 rectangles ={x=0 y=0 w=76 h=26}; 001:<:011a: 20: Request(56): ChangeGC gc=0x0560000b values={foreground=0x00d4d0c8 background=0x00d4d0c8} 001:<:011b: 20: Request(70): PolyFillRectangle drawable=0x05e00006 gc=0x0560000b rectangles={x=36 y=16 w=75 h=25}; 001:<:011c: 20: Request(56): ChangeGC gc=0x0560000b values={foreground=0x00000000 join-style=Miter(0x00)} 001:<:011d: 20: Request(67): PolyRectangle drawable=0x05e00006 gc=0x0560000b rectangles={x=36 y=16 w=75 h=25}; 001:<:011e: 20: Request(56): ChangeGC gc=0x0560000b values={foreground=0x00ffffff join-style=Round(0x01)} 001:<:011f: 28: Request(66): PolySegment drawable=0x05e00006 gc=0x0560000b segments={x1=37 y1=17 x2=111 y2=17},{x1=37 y1=17 x2=37 y2=41}; 001:<:0120: 16: Request(56): ChangeGC gc=0x0560000b values={foreground=0x00404040} 001:<:0121: 28: Request(66): PolySegment drawable=0x05e00006 gc=0x0560000b segments={x1=110 y1=40 x2=36 y2=40},{x1=110 y1=40 x2=110 y2=16}; 001:<:0122: 16: Request(56): ChangeGC gc=0x0560000b values={foreground=0x00d4d0c8} 001:<:0123: 28: Request(66): PolySegment drawable=0x05e00006 gc=0x0560000b segments={x1=38 y1=18 x2=110 y2=18},{x1=38 y1=18 x2=38 y2=40}; 001:<:0124: 16: Request(56): ChangeGC gc=0x0560000b values={foreground=0x00808080} 001:<:0125: 28: Request(66): PolySegment drawable=0x05e00006 gc=0x0560000b segments={x1=109 y1=39 x2=37 y2=39},{x1=109 y1=39 x2=109 y2=17}; 001:<:0126: 16: Request(56): ChangeGC gc=0x0560000b values={foreground=0x00d4d0c8} 001:<:0127: 20: Request(70): PolyFillRectangle drawable=0x05e00006 gc=0x0560000b rectangles={x=39 y=19 w=70 h=20}; I have made the tests with a small program showing a dialog box just with a button. If you need more information, or if this is not enough just ask for more info, I'll be more than glad to help with this bug. If you need the source code of the test program or the complete output of the xtrace I'll attach it. Created attachment 28240 [details]
The problem With the intel Driver
Ok, I think I found the problem. Is in the PolySegment call. When the X1 or Y1 is bigger than X2 or Y2 the function is drawing the segments one pixel less than is supposed to be. I think the images will explain better.
Created attachment 28241 [details]
The same program using Vesa driver
(In reply to comment #7) > Ok, I think I found the problem. Is in the PolySegment call. When the X1 or Y1 > is bigger than X2 or Y2 the function is drawing the segments one pixel less > than is supposed to be. I think the images will explain better. Excellent! Thank you very much for your careful research on this one. The ball is definitely in my court now to see what our driver is doing wrong. Please ping me if you don't hear any progress from me in the next week or two. -Carl Hi Carl, any progress in this bug?? This is still a problem. Is there any additional information I can give to quickly fix this bug?. Carl you told me to ping you in 2 weeks but I haven't heard anything from you in a month. (In reply to comment #11) > This is still a problem. Is there any additional information I can give to > quickly fix this bug?. Carl you told me to ping you in 2 weeks but I haven't > heard anything from you in a month. Hi Jaime, I apologize that I missed your first ping. I appreciated the second one, (it mentioned that I had actually *asked* for it so it was easier to notice). Anyway, I tried writing a test program based on your xtrace output, but I couldn't reproduce the bug exactly. I did succeed in getting the intel driver to generate results like in your output, but my test program achieved the same results with the vesa driver as well. Could you send me your test program? One source of differences is that your xtrace output doesn't have all of the GC settings and there are several that are relevant here, (such as line-width and cap-style). Thanks, -Carl Created attachment 29156 [details]
Test program
Hi Carl. This is the program i used to get the xtrace. It just create a message window with a button that show the bug in the right bottom corner. Anything else just ask for it.
Created attachment 29196 [details] Test program to demonstrate differing zero-width-line algorithms (In reply to comment #13) > Created an attachment (id=29156) [details] > Test program > > Hi Carl. This is the program i used to get the xtrace. It just create a message > window with a button that show the bug in the right bottom corner. Anything > else just ask for it. Hi Jaime, Thanks for the test program. I'm now attaching a test program that is as minimal as possible and that shows different behavior with either the vesa or xf86-video-intel drivers. However, this isn't actually a driver bug. Instead, the test program (and wine) are drawing lines with width of 0, (known as "thin lines" in the X protocol description). And such lines can be implemented with a device-specific algorithm that can differ from driver to driver[*]. So it's not actually surprising that there are differences here---that's perfectly allowable. What is a bit surprising is that the results with the intel driver are equivalent to the results that would be obtained by using a line width of 1, (where the protocol specifies an algorithm that defines precisely which pixels must be affected). I would have expected the vesa driver to match that behavior. The "wide lines" (such as line_width=1) specification requires that drawing a segment (x1,y1)-(x2,y2) be equivalent to drawing from (x2,y2)-(x1,y1). The protocol specification recommends, (but does not require), that "thin lines" also meet this same constraint. Interestingly, the intel driver appears to meet this constraint, but the vesa driver does not. So, according to what I can read of the X protocol specification, neither the vesa nor intel drivers have a bug here. They are allowed to differ in these details of which pixels get lit. (And if anything, vesa is the odd one for not matching the algorithm of line_width=1.) So, to fix the bug, wine is going to have to change its code to not rely on the pixelization of zero-width lines, (which can differ from one driver to the next), and should instead use lines with width=1. Making this change will require making some adjustments to how the segment endpoint coordinates are computed to still achieve the desired result. I hope this helps, (and that my test program is useful for anyone looking into this problem). And of course, another option is to stop using things like XDrawSegment entirely and instead use something like cairo (http://cairographics.org) which always provides consistent pixelization regardless of drivers. Good luck! [*] Here are some of the details from the specification: Wide lines are drawn centered on the path described by the graphics request. Unless otherwise specified by the join-style or cap-style, the bounding box of a wide line with endpoints [x1, y1], [x2, y2] and width w is a rectangle with vertices at the following real coordinates: [x1-(w*sn/2), y1+(w*cs/2)], [x1+(w*sn/2), y1-(w*cs/2)], [x2-(w*sn/2), y2+(w*cs/2)], [x2+(w*sn/2), y2-(w*cs/2)] Here sn is the sine of the angle of the line, and cs is the cosine of the angle of the line. A pixel is part of the line and so is drawn if the center of the pixel is fully inside the bounding box (which is viewed as having infinitely thin edges). If the center of the pixel is exactly on the bounding box, it is part of the line if and only if the interior is immediately to its right (x increasing direction). Pixels with centers on a horizontal edge are a special case and are part of the line if and only if the interior or the boundary is immediately below (y increasing direction) and the interior or the boundary is immediately to the right (x increasing direction). Thin lines (zero line-width) are one-pixel-wide lines drawn using an unspecified, device-dependent algorithm. There are only two constraints on this algorithm. 1. If a line is drawn unclipped from [x1,y1] to [x2,y2] and if another line is drawn unclipped from [x1+dx,y1+dy] to [x2+dx,y2+dy], a point [x,y] is touched by drawing the first line if and only if the point [x+dx,y+dy] is touched by drawing the second line. 2. The effective set of points comprising a line cannot be affected by clipping. That is, a point is touched in a clipped line if and only if the point lies inside the clipping region and the point would be touched by the line when drawn unclipped. A wide line drawn from [x1,y1] to [x2,y2] always draws the same pixels as a wide line drawn from [x2,y2] to [x1,y1], not counting cap-style and join-style. It is recommended that this property be true for thin lines, but this is not required. A line-width of zero may differ from a line-width of one in which pixels are drawn. This permits the use of many manufacturers' line drawing hardware, which may run many times faster than the more precisely specified wide lines. http://tronche.com/gui/x/xlib/GC/manipulating.html Retitling the bug report now that it has been investigated more closely, and resolving as not a bug. Thanks again for the report, -Carl Hi Carl, I know that this bug is already resolved as "not a bug", but I've been testing in other PC with Nvidia cards and the bug is not there either. And also changing the line with to 1 in wine looks like it doesn't fix the bug. I've been rechecking and the problem seems to be that when Wine make this call: 001:<:0121: 28: Request(66): PolySegment drawable=0x05e00006 gc=0x0560000b segments={x1=110 y1=40 x2=36 y2=40},{x1=110 y1=40 x2=110 y2=16}; It specs the line to be drawn from x1=110 to x2=36 and not drawing the last pixel in x=36 as when line_with is 0 or 1 in Wine they are using the CapStyle as CapNotLast [1]. But it's been draw from x=36 to x=110 and the one that is missing is the one at x=110. So looks like it is a bug in the driver after all. Thanks in advance for the help. [1]http://source.winehq.org/source/dlls/winex11.drv/graphics.c#L321 Fixed in Wine. |
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.