1 /*
2 * Copyright (c) 2017, 2018, 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 package sun.java2d.xr;
26
27 import java.nio.ByteBuffer;
28 import java.util.HashMap;
29 import java.util.LinkedList;
30
31 /**
32 * Manages the state of the buffers for uploading the AA tiles.
33 * There is always only one non-Shared-memory buffer (can be re-used immediatly
34 * once XPutImage is issued), and a vrious number of SHM buffers in case SHM
35 * is supported on the system.
36 *
37 * @author Clemens Eisserer
38 */
39 public class AATileBufMan {
40
41 private static int SHM_NUM_BUFFERS = 4;
42 private final static int TILE_BUF_WIDTH = 256;
43 private final static int TILE_BUF_HEIGHT = 256;
44
45 ByteBuffer shmBuffer;
46 int shmBufferScan;
47
48 AATileBuffer nonShmTile;
49
50 AATileBuffer activeTile;
51 LinkedList<AATileBuffer> idleShmMasks;
52 HashMap<Long, AATileBuffer> pendingShmMasks;
53 AATileBuffer fenceQueuePendingTile;
54
55 int shmCnt;
56 int noShmCnt;
57
58 int maskPicture;
59 int maskPixmap;
60 long maskGC;
61
62 public AATileBufMan() {
63 idleShmMasks = new LinkedList<>();
64 pendingShmMasks = new HashMap<>();
65
66 nonShmTile = new AATileBuffer(this, TILE_BUF_WIDTH, TILE_BUF_HEIGHT, TILE_BUF_WIDTH, 0, 0, ByteBuffer.allocateDirect(TILE_BUF_WIDTH * TILE_BUF_HEIGHT), false);
67
68 String shmProp = System.getProperty("sun.java2d.xr.shm");
69
70 if(shmProp == null || shmProp.length() > 0
71 && Character.toLowerCase(shmProp.charAt(0)) == 'f') {
72 if(System.getProperty("sun.java2d.shmBuffers") != null) {
73 SHM_NUM_BUFFERS = Integer.parseInt(System.getProperty("sun.java2d.shmBuffers"));
74 }
75
76 if((shmBuffer = initShmImage(TILE_BUF_WIDTH, TILE_BUF_HEIGHT * SHM_NUM_BUFFERS)) != null) {
77 for(int i = 0; i < SHM_NUM_BUFFERS; i++) {
78 int tileYOffset = TILE_BUF_HEIGHT * i;
79
80 shmBuffer.position(tileYOffset * shmBufferScan);
81 ByteBuffer tileBuffer = shmBuffer.slice();
82 AATileBuffer aaShmBuf = new AATileBuffer(this, TILE_BUF_WIDTH, TILE_BUF_HEIGHT, shmBufferScan, tileYOffset, i + 1, tileBuffer, true);
83 idleShmMasks.add(aaShmBuf);
84 }
85
86 }
87
88 shmBuffer.position(0);
89 }
90 }
91
92 public void initResources(XRBackendDeferred con, int parentXID) {
93 maskPixmap = con.createPixmap(parentXID, 8, TILE_BUF_WIDTH, TILE_BUF_HEIGHT);
94 maskPicture = con.createPicture(maskPixmap, XRUtils.PictStandardA8);
95 maskGC = con.createGC(maskPixmap);
96 con.setGCExposures(maskGC, false);
97 }
98
99
100 public AATileBuffer getActiveTileBuffer() {
101 if(activeTile != null) {
102 return activeTile;
103 }
104
105 if(idleShmMasks.size() > 0) {
106 //System.out.println("shm tiles available: "+idleShmMasks.size());
107 activeTile = idleShmMasks.removeLast();
108 shmCnt++;
109 } else {
110 //System.out.println("shmtiles exhausted");
111 activeTile = nonShmTile;
112 noShmCnt++;
113 }
114
115 if(((shmCnt + noShmCnt) % 10000 == 0)) {
116 System.out.println("Shm: "+shmCnt+" noShm:"+noShmCnt);
117 }
118
119 return activeTile;
120 }
121
122 public void pollPendingFences() {
123 if(pendingShmMasks.size() > 0) {
124 java.util.Iterator<Long> shmSeqIt = pendingShmMasks.keySet().iterator();
125
126 while(shmSeqIt.hasNext()) {
127 long pendingSeq = shmSeqIt.next();
128
129 if(pollForTileCompletion(pendingSeq)) {
130 // System.out.println("Pending fence received: " + pendingSeq);
131 AATileBuffer idleBuffer = pendingShmMasks.get(pendingSeq);
132 // System.out.println("tile now available again: "+idleBuffer.getTileId());
133 idleShmMasks.add(idleBuffer);
134
135 shmSeqIt.remove();
136 }
137 }
138 }
139 }
140
141 public void registerFenceSeqForActiveBuffer(long seq) {
142 assert(fenceQueuePendingTile != null);
143 pendingShmMasks.put(seq, fenceQueuePendingTile);
144 // System.out.println("fence queued for tile: "+fenceQueuePendingTile.getTileId());
145 fenceQueuePendingTile = null;
146 }
147
148
149 public void markActiveBufferFlushed(boolean shmQueued) {
150 if(shmQueued) {
151 // pendingShmMasks.push(activeTile);
152 assert (fenceQueuePendingTile == null);
153 fenceQueuePendingTile = activeTile;
154 } else if(activeTile != nonShmTile) {
155 idleShmMasks.add(activeTile);
156 }
157
158 activeTile.reset();
159 activeTile = null;
160 }
161
162 public int getIdleShmBufferCnt() {
163 return idleShmMasks.size();
164 }
165
166 public boolean isFencePending() {
167 return fenceQueuePendingTile != null;
168 }
169
170 public int getMaskPictureXid() {
171 return maskPicture;
172 }
173
174 public long getMaskGCPtr() {
175 return maskGC;
176 }
177
178 public int getMaskPixmapXid() {
179 return maskPixmap;
180 }
181
182 private native ByteBuffer initShmImage(int width, int height);
183
184 private native boolean pollForTileCompletion(long fenceSeq);
185
186 }