History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/java2d/pipe/BufferedContext.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/java2d/pipe/BufferedContext.java+470−0
@@ -0,0 +1,470 @@
1+/*
2+ * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.AlphaComposite;
29+import java.awt.Color;
30+import java.awt.Composite;
31+import java.awt.Paint;
32+import java.awt.geom.AffineTransform;
33+import sun.java2d.pipe.hw.AccelSurface;
34+import sun.java2d.InvalidPipeException;
35+import sun.java2d.SunGraphics2D;
36+import sun.java2d.loops.XORComposite;
37+import static sun.java2d.pipe.BufferedOpCodes.*;
38+import static sun.java2d.pipe.BufferedRenderPipe.BYTES_PER_SPAN;
39+
40+/**
41+ * Base context class for managing state in a single-threaded rendering
42+ * environment. Each state-setting operation (e.g. SET_COLOR) is added to
43+ * the provided RenderQueue, which will be processed at a later time by a
44+ * single thread. Note that the RenderQueue lock must be acquired before
45+ * calling the validate() method (or any other method in this class). See
46+ * the RenderQueue class comments for a sample usage scenario.
47+ *
48+ * @see RenderQueue
49+ */
50+public abstract class BufferedContext {
51+
52+ /*
53+ * The following flags help the internals of validate() determine
54+ * the appropriate (meaning correct, or optimal) code path when
55+ * setting up the current context. The flags can be bitwise OR'd
56+ * together as needed.
57+ */
58+
59+ /**
60+ * Indicates that no flags are needed; take all default code paths.
61+ */
62+ public static final int NO_CONTEXT_FLAGS = (0 << 0);
63+ /**
64+ * Indicates that the source surface (or color value, if it is a simple
65+ * rendering operation) is opaque (has an alpha value of 1.0). If this
66+ * flag is present, it allows us to disable blending in certain
67+ * situations in order to improve performance.
68+ */
69+ public static final int SRC_IS_OPAQUE = (1 << 0);
70+ /**
71+ * Indicates that the operation uses an alpha mask, which may determine
72+ * the code path that is used when setting up the current paint state.
73+ */
74+ public static final int USE_MASK = (1 << 1);
75+
76+ protected RenderQueue rq;
77+ protected RenderBuffer buf;
78+
79+ /**
80+ * This is a reference to the most recently validated BufferedContext. If
81+ * this value is null, it means that there is no current context. It is
82+ * provided here so that validate() only needs to do a quick reference
83+ * check to see if the BufferedContext passed to that method is the same
84+ * as the one we've cached here.
85+ */
86+ protected static BufferedContext currentContext;
87+
88+ private AccelSurface validatedSrcData;
89+ private AccelSurface validatedDstData;
90+ private Region validatedClip;
91+ private Composite validatedComp;
92+ private Paint validatedPaint;
93+ // renamed from isValidatedPaintAColor as part of a work around for 6764257
94+ private boolean isValidatedPaintJustAColor;
95+ private int validatedRGB;
96+ private int validatedFlags;
97+ private boolean xformInUse;
98+ private int transX;
99+ private int transY;
100+
101+ protected BufferedContext(RenderQueue rq) {
102+ this.rq = rq;
103+ this.buf = rq.getBuffer();
104+ }
105+
106+ /**
107+ * Fetches the BufferedContextContext associated with the dst. surface
108+ * and validates the context using the given parameters. Most rendering
109+ * operations will call this method first in order to set the necessary
110+ * state before issuing rendering commands.
111+ *
112+ * Note: must be called while the RenderQueue lock is held.
113+ *
114+ * @throws InvalidPipeException if either src or dest surface is not valid
115+ * or lost
116+ * @see RenderQueue#lock
117+ * @see RenderQueue#unlock
118+ */
119+ public static void validateContext(AccelSurface srcData,
120+ AccelSurface dstData,
121+ Region clip, Composite comp,
122+ AffineTransform xform,
123+ Paint paint, SunGraphics2D sg2d,
124+ int flags)
125+ {
126+ // assert rq.lock.isHeldByCurrentThread();
127+ BufferedContext d3dc = dstData.getContext();
128+ d3dc.validate(srcData, dstData,
129+ clip, comp, xform, paint, sg2d, flags);
130+ }
131+
132+ /**
133+ * Fetches the BufferedContextassociated with the surface
134+ * and disables all context state settings.
135+ *
136+ * Note: must be called while the RenderQueue lock is held.
137+ *
138+ * @throws InvalidPipeException if the surface is not valid
139+ * or lost
140+ * @see RenderQueue#lock
141+ * @see RenderQueue#unlock
142+ */
143+ public static void validateContext(AccelSurface surface) {
144+ // assert rt.lock.isHeldByCurrentThread();
145+ validateContext(surface, surface,
146+ null, null, null, null, null, NO_CONTEXT_FLAGS);
147+ }
148+
149+ /**
150+ * Validates the given parameters against the current state for this
151+ * context. If this context is not current, it will be made current
152+ * for the given source and destination surfaces, and the viewport will
153+ * be updated. Then each part of the context state (clip, composite,
154+ * etc.) is checked against the previous value. If the value has changed
155+ * since the last call to validate(), it will be updated accordingly.
156+ *
157+ * Note that the SunGraphics2D parameter is only used for the purposes
158+ * of validating a (non-null) Paint parameter. In all other cases it
159+ * is safe to pass a null SunGraphics2D and it will be ignored.
160+ *
161+ * Note: must be called while the RenderQueue lock is held.
162+ *
163+ * @throws InvalidPipeException if either src or dest surface is not valid
164+ * or lost
165+ */
166+ public void validate(AccelSurface srcData, AccelSurface dstData,
167+ Region clip, Composite comp,
168+ AffineTransform xform,
169+ Paint paint, SunGraphics2D sg2d, int flags)
170+ {
171+ // assert rq.lock.isHeldByCurrentThread();
172+
173+ boolean updateClip = false;
174+ boolean updatePaint = false;
175+
176+ if (!dstData.isValid() ||
177+ dstData.isSurfaceLost() || srcData.isSurfaceLost())
178+ {
179+ invalidateContext();
180+ throw new InvalidPipeException("bounds changed or surface lost");
181+ }
182+
183+ if (paint instanceof Color) {
184+ // REMIND: not 30-bit friendly
185+ int newRGB = ((Color)paint).getRGB();
186+ if (isValidatedPaintJustAColor) {
187+ if (newRGB != validatedRGB) {
188+ validatedRGB = newRGB;
189+ updatePaint = true;
190+ }
191+ } else {
192+ validatedRGB = newRGB;
193+ updatePaint = true;
194+ isValidatedPaintJustAColor = true;
195+ }
196+ } else if (validatedPaint != paint) {
197+ updatePaint = true;
198+ // this should be set when we are switching from paint to color
199+ // in which case this condition will be true
200+ isValidatedPaintJustAColor = false;
201+ }
202+
203+ if ((currentContext != this) ||
204+ (srcData != validatedSrcData) ||
205+ (dstData != validatedDstData))
206+ {
207+ if (dstData != validatedDstData) {
208+ // the clip is dependent on the destination surface, so we
209+ // need to update it if we have a new destination surface
210+ updateClip = true;
211+ }
212+
213+ if (paint == null) {
214+ // make sure we update the color state (otherwise, it might
215+ // not be updated if this is the first time the context
216+ // is being validated)
217+ updatePaint = true;
218+ }
219+
220+ // update the current source and destination surfaces
221+ setSurfaces(srcData, dstData);
222+
223+ currentContext = this;
224+ validatedSrcData = srcData;
225+ validatedDstData = dstData;
226+ }
227+
228+ // validate clip
229+ if ((clip != validatedClip) || updateClip) {
230+ if (clip != null) {
231+ if (updateClip ||
232+ validatedClip == null ||
233+ !(validatedClip.isRectangular() && clip.isRectangular()) ||
234+ ((clip.getLoX() != validatedClip.getLoX() ||
235+ clip.getLoY() != validatedClip.getLoY() ||
236+ clip.getHiX() != validatedClip.getHiX() ||
237+ clip.getHiY() != validatedClip.getHiY())))
238+ {
239+ setClip(clip);
240+ }
241+ } else {
242+ resetClip();
243+ }
244+ validatedClip = clip;
245+ }
246+
247+ // validate composite (note that a change in the context flags
248+ // may require us to update the composite state, even if the
249+ // composite has not changed)
250+ if ((comp != validatedComp) || (flags != validatedFlags)) {
251+ if (comp != null) {
252+ setComposite(comp, flags);
253+ } else {
254+ resetComposite();
255+ }
256+ // the paint state is dependent on the composite state, so make
257+ // sure we update the color below
258+ updatePaint = true;
259+ validatedComp = comp;
260+ validatedFlags = flags;
261+ }
262+
263+ // validate transform
264+ boolean txChanged = false;
265+ if (xform == null) {
266+ if (xformInUse) {
267+ resetTransform();
268+ xformInUse = false;
269+ txChanged = true;
270+ } else if (sg2d != null) {
271+ if (transX != sg2d.transX || transY != sg2d.transY) {
272+ txChanged = true;
273+ }
274+ }
275+ if (sg2d != null) {
276+ transX = sg2d.transX;
277+ transY = sg2d.transY;
278+ }
279+ } else {
280+ setTransform(xform);
281+ xformInUse = true;
282+ txChanged = true;
283+ }
284+ // non-Color paints may require paint revalidation
285+ if (!isValidatedPaintJustAColor && txChanged) {
286+ updatePaint = true;
287+ }
288+
289+ // validate paint
290+ if (updatePaint) {
291+ if (paint != null) {
292+ BufferedPaints.setPaint(rq, sg2d, paint, flags);
293+ } else {
294+ BufferedPaints.resetPaint(rq);
295+ }
296+ validatedPaint = paint;
297+ }
298+
299+ // mark dstData dirty
300+ // REMIND: is this really needed now? we do it in SunGraphics2D..
301+ dstData.markDirty();
302+ }
303+
304+ /**
305+ * Invalidates the surfaces associated with this context. This is
306+ * useful when the context is no longer needed, and we want to break
307+ * the chain caused by these surface references.
308+ *
309+ * Note: must be called while the RenderQueue lock is held.
310+ *
311+ * @see RenderQueue#lock
312+ * @see RenderQueue#unlock
313+ */
314+ public void invalidateSurfaces() {
315+ validatedSrcData = null;
316+ validatedDstData = null;
317+ }
318+
319+ private void setSurfaces(AccelSurface srcData,
320+ AccelSurface dstData)
321+ {
322+ // assert rq.lock.isHeldByCurrentThread();
323+ rq.ensureCapacityAndAlignment(20, 4);
324+ buf.putInt(SET_SURFACES);
325+ buf.putLong(srcData.getNativeOps());
326+ buf.putLong(dstData.getNativeOps());
327+ }
328+
329+ private void resetClip() {
330+ // assert rq.lock.isHeldByCurrentThread();
331+ rq.ensureCapacity(4);
332+ buf.putInt(RESET_CLIP);
333+ }
334+
335+ private void setClip(Region clip) {
336+ // assert rq.lock.isHeldByCurrentThread();
337+ if (clip.isRectangular()) {
338+ rq.ensureCapacity(20);
339+ buf.putInt(SET_RECT_CLIP);
340+ buf.putInt(clip.getLoX()).putInt(clip.getLoY());
341+ buf.putInt(clip.getHiX()).putInt(clip.getHiY());
342+ } else {
343+ rq.ensureCapacity(28); // so that we have room for at least a span
344+ buf.putInt(BEGIN_SHAPE_CLIP);
345+ buf.putInt(SET_SHAPE_CLIP_SPANS);
346+ // include a placeholder for the span count
347+ int countIndex = buf.position();
348+ buf.putInt(0);
349+ int spanCount = 0;
350+ int remainingSpans = buf.remaining() / BYTES_PER_SPAN;
351+ int span[] = new int[4];
352+ SpanIterator si = clip.getSpanIterator();
353+ while (si.nextSpan(span)) {
354+ if (remainingSpans == 0) {
355+ buf.putInt(countIndex, spanCount);
356+ rq.flushNow();
357+ buf.putInt(SET_SHAPE_CLIP_SPANS);
358+ countIndex = buf.position();
359+ buf.putInt(0);
360+ spanCount = 0;
361+ remainingSpans = buf.remaining() / BYTES_PER_SPAN;
362+ }
363+ buf.putInt(span[0]); // x1
364+ buf.putInt(span[1]); // y1
365+ buf.putInt(span[2]); // x2
366+ buf.putInt(span[3]); // y2
367+ spanCount++;
368+ remainingSpans--;
369+ }
370+ buf.putInt(countIndex, spanCount);
371+ rq.ensureCapacity(4);
372+ buf.putInt(END_SHAPE_CLIP);
373+ }
374+ }
375+
376+ private void resetComposite() {
377+ // assert rq.lock.isHeldByCurrentThread();
378+ rq.ensureCapacity(4);
379+ buf.putInt(RESET_COMPOSITE);
380+ }
381+
382+ private void setComposite(Composite comp, int flags) {
383+ // assert rq.lock.isHeldByCurrentThread();
384+ if (comp instanceof AlphaComposite) {
385+ AlphaComposite ac = (AlphaComposite)comp;
386+ rq.ensureCapacity(16);
387+ buf.putInt(SET_ALPHA_COMPOSITE);
388+ buf.putInt(ac.getRule());
389+ buf.putFloat(ac.getAlpha());
390+ buf.putInt(flags);
391+ } else if (comp instanceof XORComposite) {
392+ int xorPixel = ((XORComposite)comp).getXorPixel();
393+ rq.ensureCapacity(8);
394+ buf.putInt(SET_XOR_COMPOSITE);
395+ buf.putInt(xorPixel);
396+ } else {
397+ throw new InternalError("not yet implemented");
398+ }
399+ }
400+
401+ private void resetTransform() {
402+ // assert rq.lock.isHeldByCurrentThread();
403+ rq.ensureCapacity(4);
404+ buf.putInt(RESET_TRANSFORM);
405+ }
406+
407+ private void setTransform(AffineTransform xform) {
408+ // assert rq.lock.isHeldByCurrentThread();
409+ rq.ensureCapacityAndAlignment(52, 4);
410+ buf.putInt(SET_TRANSFORM);
411+ buf.putDouble(xform.getScaleX());
412+ buf.putDouble(xform.getShearY());
413+ buf.putDouble(xform.getShearX());
414+ buf.putDouble(xform.getScaleY());
415+ buf.putDouble(xform.getTranslateX());
416+ buf.putDouble(xform.getTranslateY());
417+ }
418+
419+ /**
420+ * Resets this context's surfaces and all attributes.
421+ *
422+ * Note: must be called while the RenderQueue lock is held.
423+ *
424+ * @see RenderQueue#lock
425+ * @see RenderQueue#unlock
426+ */
427+ public void invalidateContext() {
428+ resetTransform();
429+ resetComposite();
430+ resetClip();
431+ BufferedPaints.resetPaint(rq);
432+ invalidateSurfaces();
433+ validatedComp = null;
434+ validatedClip = null;
435+ validatedPaint = null;
436+ isValidatedPaintJustAColor = false;
437+ xformInUse = false;
438+ }
439+
440+ /**
441+ * Returns a singleton {@code RenderQueue} object used by the rendering
442+ * pipeline.
443+ *
444+ * @return a render queue
445+ * @see RenderQueue
446+ */
447+ public abstract RenderQueue getRenderQueue();
448+
449+ /**
450+ * Saves the the state of this context.
451+ * It may reset the current context.
452+ *
453+ * Note: must be called while the RenderQueue lock is held.
454+ *
455+ * @see RenderQueue#lock
456+ * @see RenderQueue#unlock
457+ */
458+ public abstract void saveState();
459+
460+ /**
461+ * Restores the native state of this context.
462+ * It may reset the current context.
463+ *
464+ * Note: must be called while the RenderQueue lock is held.
465+ *
466+ * @see RenderQueue#lock
467+ * @see RenderQueue#unlock
468+ */
469+ public abstract void restoreState();
470+}