1/*
2 * Copyright (c) 2007, 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#include <malloc.h>
27#include <string.h>
28
29#include "ShaderList.h"
30#include "Trace.h"
31
32/**
33 * Creates a new ShaderInfo that wraps the given fragment program handle
34 * and related data and stores it at the front of the provided ShaderList.
35 * If the addition causes the ShaderList to outgrow its defined capacity,
36 * the least-recently used item in the list (including its fragment program
37 * object) will be disposed.
38 */
39void
40ShaderList_AddProgram(ShaderList *programList,
41                      jlong programID,
42                      jint compType, jint compMode, jint flags)
43{
44    ShaderInfo *info;
45
46    J2dTraceLn(J2D_TRACE_INFO, "ShaderList_AddProgram");
47
48    // create new ShaderInfo
49    info = (ShaderInfo *)malloc(sizeof(ShaderInfo));
50    if (info == NULL) {
51        J2dTraceLn(J2D_TRACE_ERROR,
52                   "D3DContext_AddProgram: could not allocate ShaderInfo");
53        return;
54    }
55
56    // fill in the information
57    info->next = programList->head;
58    info->programID = programID;
59    info->compType = compType;
60    info->compMode = compMode;
61    info->flags = flags;
62
63    // insert it at the head of the list
64    programList->head = info;
65
66    // run through the list and see if we need to delete the least
67    // recently used item
68    {
69        int i = 1;
70        ShaderInfo *prev = NULL;
71        ShaderInfo *curr = info->next;
72        while (curr != NULL) {
73            if (i >= programList->maxItems) {
74                prev->next = NULL;
75                programList->dispose(curr->programID);
76                free(curr);
77                break;
78            }
79            i++;
80            prev = curr;
81            curr = curr->next;
82        }
83    }
84}
85
86/**
87 * Locates a fragment program handle given a list of shader programs
88 * (ShaderInfos), using the provided composite state and flags as search
89 * parameters.  The "flags" parameter is a bitwise-or'd value that helps
90 * differentiate one program for another; the interpretation of this value
91 * varies depending on the type of shader (BufImgOp, Paint, etc) but here
92 * it is only used to find another ShaderInfo with that same "flags" value.
93 * If no matching program can be located, this method returns 0.
94 */
95jlong
96ShaderList_FindProgram(ShaderList *programList,
97                       jint compType, jint compMode, jint flags)
98{
99    ShaderInfo *prev = NULL;
100    ShaderInfo *info = programList->head;
101
102    J2dTraceLn(J2D_TRACE_INFO, "ShaderList_FindProgram");
103
104    while (info != NULL) {
105        if (compType == info->compType &&
106            compMode == info->compMode &&
107            flags == info->flags)
108        {
109            // it's a match: move it to the front of the list (if it's not
110            // there already) and patch up the links
111            if (info != programList->head) {
112                prev->next = info->next;
113                info->next = programList->head;
114                programList->head = info;
115            }
116            return info->programID;
117        }
118        prev = info;
119        info = info->next;
120    }
121    return 0;
122}
123
124/**
125 * Disposes all entries (and their associated shader program objects)
126 * contained in the given ShaderList.
127 */
128void
129ShaderList_Dispose(ShaderList *programList)
130{
131    ShaderInfo *info = programList->head;
132
133    J2dTraceLn(J2D_TRACE_INFO, "ShaderList_Dispose");
134
135    while (info != NULL) {
136        ShaderInfo *tmp = info->next;
137        programList->dispose(info->programID);
138        free(info);
139        info = tmp;
140    }
141
142    programList->head = NULL;
143}
144